summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/media_plugins/winmmshim/forwarding_api.cpp6
-rw-r--r--indra/media_plugins/winmmshim/winmm_shim.cpp38
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;
}