if (dwFlags & WAVE_MAPPED) {\r
if (lpDesc->uMappedDeviceID >= ndhi) {\r
WARN("invalid parameter: dwFlags WAVE_MAPPED\n");\r
+ HeapFree(GetProcessHeap(), 0, wom);\r
return MMSYSERR_INVALPARAM;\r
}\r
ndlo = lpDesc->uMappedDeviceID;\r
if (lpTime->wType == TIME_MS)\r
timepos.wType = TIME_BYTES;\r
\r
+ /* This can change timepos.wType if the requested type is not supported */\r
val = waveOutGetPosition(wom->u.out.hInnerWave, &timepos, dwParam2);\r
\r
- if (lpTime->wType == TIME_BYTES || lpTime->wType == TIME_MS)\r
+ if (timepos.wType == TIME_BYTES)\r
{\r
DWORD dwInnerSamplesPerOuter = wom->nSamplesPerSecInner / wom->nSamplesPerSecOuter;\r
if (dwInnerSamplesPerOuter > 0)\r
\r
/* Once we have the TIME_BYTES right, we can easily convert to TIME_MS */\r
if (lpTime->wType == TIME_MS)\r
- lpTime->u.cb = MulDiv(lpTime->u.cb, 1000, wom->avgSpeedOuter);\r
+ lpTime->u.ms = MulDiv(lpTime->u.cb, 1000, wom->avgSpeedOuter);\r
+ else\r
+ lpTime->wType = TIME_BYTES;\r
}\r
- else if (lpTime->wType == TIME_SAMPLES)\r
- lpTime->u.cb = MulDiv(timepos.u.cb, wom->nSamplesPerSecOuter, wom->nSamplesPerSecInner);\r
+ else if (lpTime->wType == TIME_SAMPLES && timepos.wType == TIME_SAMPLES)\r
+ lpTime->u.sample = MulDiv(timepos.u.sample, wom->nSamplesPerSecOuter, wom->nSamplesPerSecInner);\r
else\r
/* other time types don't require conversion */\r
lpTime->u = timepos.u;\r
return ret;\r
}\r
\r
+static DWORD wodMapperReconfigure(WAVEMAPDATA* wom, DWORD dwParam1, DWORD dwParam2)\r
+{\r
+ FIXME("(%p %08lx %08lx) stub!\n", wom, dwParam1, dwParam2);\r
+\r
+ return MMSYSERR_NOERROR;\r
+}\r
+\r
/**************************************************************************\r
* wodMessage (MSACM.@)\r
*/\r
case WODM_RESTART: return wodRestart ((WAVEMAPDATA*)dwUser);\r
case WODM_RESET: return wodReset ((WAVEMAPDATA*)dwUser);\r
case WODM_MAPPER_STATUS: return wodMapperStatus ((WAVEMAPDATA*)dwUser, dwParam1, (LPVOID)dwParam2);\r
+ case DRVM_MAPPER_RECONFIGURE: return wodMapperReconfigure((WAVEMAPDATA*)dwUser, dwParam1, dwParam2);\r
/* known but not supported */\r
case DRV_QUERYDEVICEINTERFACESIZE:\r
case DRV_QUERYDEVICEINTERFACE:\r
static DWORD widGetPosition(WAVEMAPDATA* wim, LPMMTIME lpTime, DWORD dwParam2)\r
{\r
DWORD val;\r
-\r
+ MMTIME timepos;\r
TRACE("(%p %p %08lx)\n", wim, lpTime, dwParam2);\r
\r
- val = waveInGetPosition(wim->u.in.hInnerWave, lpTime, dwParam2);\r
- if (lpTime->wType == TIME_BYTES)\r
- lpTime->u.cb = MulDiv(lpTime->u.cb, wim->avgSpeedOuter, wim->avgSpeedInner);\r
- if (lpTime->wType == TIME_SAMPLES)\r
- lpTime->u.cb = MulDiv(lpTime->u.cb, wim->nSamplesPerSecOuter, wim->nSamplesPerSecInner);\r
- /* other time types don't require conversion */\r
+ memcpy(&timepos, lpTime, sizeof(timepos));\r
+\r
+ /* For TIME_MS, we're going to recalculate using TIME_BYTES */\r
+ if (lpTime->wType == TIME_MS)\r
+ timepos.wType = TIME_BYTES;\r
+\r
+ /* This can change timepos.wType if the requested type is not supported */\r
+ val = waveInGetPosition(wim->u.in.hInnerWave, &timepos, dwParam2);\r
+\r
+ if (timepos.wType == TIME_BYTES)\r
+ {\r
+ DWORD dwInnerSamplesPerOuter = wim->nSamplesPerSecInner / wim->nSamplesPerSecOuter;\r
+ if (dwInnerSamplesPerOuter > 0)\r
+ {\r
+ DWORD dwInnerBytesPerSample = wim->avgSpeedInner / wim->nSamplesPerSecInner;\r
+ DWORD dwInnerBytesPerOuterSample = dwInnerBytesPerSample * dwInnerSamplesPerOuter;\r
+ DWORD remainder = 0;\r
+\r
+ /* If we are up sampling (going from lower sample rate to higher),\r
+ ** we need to make a special accomodation for times when we've\r
+ ** written a partial output sample. This happens frequently\r
+ ** to us because we use msacm to do our up sampling, and it\r
+ ** will up sample on an unaligned basis.\r
+ ** For example, if you convert a 2 byte wide 8,000 'outer'\r
+ ** buffer to a 2 byte wide 48,000 inner device, you would\r
+ ** expect 2 bytes of input to produce 12 bytes of output.\r
+ ** Instead, msacm will produce 8 bytes of output.\r
+ ** But reporting our position as 1 byte of output is\r
+ ** nonsensical; the output buffer position needs to be\r
+ ** aligned on outer sample size, and aggressively rounded up.\r
+ */\r
+ remainder = timepos.u.cb % dwInnerBytesPerOuterSample;\r
+ if (remainder > 0)\r
+ {\r
+ timepos.u.cb -= remainder;\r
+ timepos.u.cb += dwInnerBytesPerOuterSample;\r
+ }\r
+ }\r
+\r
+ lpTime->u.cb = MulDiv(timepos.u.cb, wim->avgSpeedOuter, wim->avgSpeedInner);\r
+\r
+ /* Once we have the TIME_BYTES right, we can easily convert to TIME_MS */\r
+ if (lpTime->wType == TIME_MS)\r
+ lpTime->u.ms = MulDiv(lpTime->u.cb, 1000, wim->avgSpeedOuter);\r
+ else\r
+ lpTime->wType = TIME_BYTES;\r
+ }\r
+ else if (lpTime->wType == TIME_SAMPLES && timepos.wType == TIME_SAMPLES)\r
+ lpTime->u.sample = MulDiv(timepos.u.sample, wim->nSamplesPerSecOuter, wim->nSamplesPerSecInner);\r
+ else\r
+ /* other time types don't require conversion */\r
+ lpTime->u = timepos.u;\r
+\r
return val;\r
}\r
\r
return ret;\r
}\r
\r
+static DWORD widMapperReconfigure(WAVEMAPDATA* wim, DWORD dwParam1, DWORD dwParam2)\r
+{\r
+ FIXME("(%p %08lx %08lx) stub!\n", wim, dwParam1, dwParam2);\r
+\r
+ return MMSYSERR_NOERROR;\r
+}\r
+\r
/**************************************************************************\r
* widMessage (MSACM.@)\r
*/\r
case WIDM_START: return widStart ((WAVEMAPDATA*)dwUser);\r
case WIDM_STOP: return widStop ((WAVEMAPDATA*)dwUser);\r
case WIDM_MAPPER_STATUS: return widMapperStatus ((WAVEMAPDATA*)dwUser, dwParam1, (LPVOID)dwParam2);\r
+ case DRVM_MAPPER_RECONFIGURE: return widMapperReconfigure((WAVEMAPDATA*)dwUser, dwParam1, dwParam2);\r
/* known but not supported */\r
case DRV_QUERYDEVICEINTERFACESIZE:\r
case DRV_QUERYDEVICEINTERFACE:\r