Float-less TIME_SMPTE code
Francois Gouget
fgouget at codeweavers.com
Fri Jul 23 12:27:06 CDT 2004
This patch is based on the code I posted to wine-devel in this email:
http://www.winehq.org/hypermail/wine-devel/2004/07/0288.html
I extended it to all the sound drivers. It does not move the code to
winmm.c as I proposed another email because winmm.c does not have access
to the sound device format (samples per seconds, etc) which makes the
calculations impossible or less precise. However for each driver I
created a bytes_to_mmtime() function which converts the position as
given in bytes, to the requested MMTIME format. This makes has two
advantages:
* it lets us share that code between wodGetPosition() and widGetPosition()
* the function can be copy/pasted between drivers with no modification
despite the minor differences from driver to driver
The other advantages of the new code are that:
* it does not use floating point arithmetic so there is no risk of
getting wrong results because of rounding errors
* some of the drivers still had potential integer overflows (e.g. val
* 8...). The new code should never overflow.
* it should also fix the FreeBSD compilation problem reported by
Gerald Pfeifer as the code will no longer use round().
Changelog:
* dlls/winmm/winealsa/audio.c
dlls/winmm/winearts/audio.c
dlls/winmm/wineaudioio/audio.c
dlls/winmm/winejack/audio.c
dlls/winmm/winenas/audio.c
dlls/winmm/wineoss/audio.c
Francois Gouget <fgouget at codeweavers.com>
Added bytes_to_mmtime() to convert the stream position from bytes to
the requested MMTIME format. This function should be identical in all
drivers.
Remove the corresponding code from wodGetPosition() and
widGetPosition() and use bytes_to_mmtime() instead.
bytes_to_mmtime() uses no floating-point arithmetic to compute
TIME_SMPTE and no longer uses round(). It should have no integer
overflows either.
--
Francois Gouget
fgouget at codeweavers.com
-------------- next part --------------
Index: dlls/winmm/winealsa/audio.c
===================================================================
RCS file: /var/cvs/wine/dlls/winmm/winealsa/audio.c,v
retrieving revision 1.47
diff -u -r1.47 audio.c
--- dlls/winmm/winealsa/audio.c 19 Jul 2004 21:20:59 -0000 1.47
+++ dlls/winmm/winealsa/audio.c 23 Jul 2004 00:58:23 -0000
@@ -258,6 +258,55 @@
};
#endif
+static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
+ PCMWAVEFORMAT* format)
+{
+ TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
+ lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
+ format->wf.nChannels, format->wf.nAvgBytesPerSec);
+ TRACE("Position in bytes=%lu\n", position);
+
+ switch (lpTime->wType) {
+ case TIME_SAMPLES:
+ lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
+ break;
+ case TIME_MS:
+ lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
+ TRACE("TIME_MS=%lu\n", lpTime->u.ms);
+ break;
+ case TIME_SMPTE:
+ position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
+ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
+ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
+ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
+ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
+ lpTime->u.smpte.fps = 30;
+ lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
+ if (position != 0)
+ {
+ /* Round up */
+ lpTime->u.smpte.frame++;
+ }
+ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
+ lpTime->u.smpte.hour, lpTime->u.smpte.min,
+ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
+ break;
+ default:
+ FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
+ lpTime->wType = TIME_BYTES;
+ /* fall through */
+ case TIME_BYTES:
+ lpTime->u.cb = position;
+ TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
/*======================================================================*
* Low level WAVE implementation *
*======================================================================*/
@@ -1835,8 +1897,6 @@
*/
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
- DWORD val;
WINE_WAVEOUT* wwo;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
@@ -1850,46 +1910,8 @@
wwo = &WOutDev[wDevID];
ALSA_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
- val = wwo->dwPlayedTotal;
- TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
- lpTime->wType, wwo->format.wBitsPerSample,
- wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
- wwo->format.wf.nAvgBytesPerSec);
- TRACE("dwPlayedTotal=%lu\n", val);
-
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = val;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = round(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- default:
- FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- case TIME_MS:
- lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
}
/**************************************************************************
@@ -3338,7 +3363,6 @@
*/
static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
WINE_WAVEIN* wwi;
FIXME("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
@@ -3352,47 +3376,7 @@
wwi = &WInDev[wDevID];
ALSA_AddRingMessage(&wwi->msgRing, WINE_WM_UPDATE, 0, TRUE);
- TRACE("wType=%04X !\n", lpTime->wType);
- TRACE("wBitsPerSample=%u\n", wwi->format.wBitsPerSample);
- TRACE("nSamplesPerSec=%lu\n", wwi->format.wf.nSamplesPerSec);
- TRACE("nChannels=%u\n", wwi->format.wf.nChannels);
- TRACE("nAvgBytesPerSec=%lu\n", wwi->format.wf.nAvgBytesPerSec);
- FIXME("dwTotalRecorded=%lu\n",wwi->dwTotalRecorded);
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = wwi->dwTotalRecorded;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = wwi->dwTotalRecorded * 8 /
- wwi->format.wBitsPerSample / wwi->format.wf.nChannels;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)wwi->dwTotalRecorded /
- (double)wwi->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = ceil(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- default:
- FIXME("format not supported (%u) ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- case TIME_MS:
- lpTime->u.ms = wwi->dwTotalRecorded * 1000.0 /
- wwi->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, wwi->dwTotalRecorded, &wwi->format);
}
/**************************************************************************
Index: dlls/winmm/winearts/audio.c
===================================================================
RCS file: /var/cvs/wine/dlls/winmm/winearts/audio.c,v
retrieving revision 1.21
diff -u -r1.21 audio.c
--- dlls/winmm/winearts/audio.c 19 Jul 2004 20:08:06 -0000 1.21
+++ dlls/winmm/winearts/audio.c 23 Jul 2004 00:58:52 -0000
@@ -222,6 +222,55 @@
"WINE_WM_STOPPING",
};
+static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
+ PCMWAVEFORMAT* format)
+{
+ TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
+ lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
+ format->wf.nChannels, format->wf.nAvgBytesPerSec);
+ TRACE("Position in bytes=%lu\n", position);
+
+ switch (lpTime->wType) {
+ case TIME_SAMPLES:
+ lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
+ break;
+ case TIME_MS:
+ lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
+ TRACE("TIME_MS=%lu\n", lpTime->u.ms);
+ break;
+ case TIME_SMPTE:
+ position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
+ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
+ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
+ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
+ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
+ lpTime->u.smpte.fps = 30;
+ lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
+ if (position != 0)
+ {
+ /* Round up */
+ lpTime->u.smpte.frame++;
+ }
+ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
+ lpTime->u.smpte.hour, lpTime->u.smpte.min,
+ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
+ break;
+ default:
+ FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
+ lpTime->wType = TIME_BYTES;
+ /* fall through */
+ case TIME_BYTES:
+ lpTime->u.cb = position;
+ TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
/*======================================================================*
* Low level WAVE implementation *
*======================================================================*/
@@ -1386,8 +1438,6 @@
*/
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
- DWORD val;
WINE_WAVEOUT* wwo;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
@@ -1403,46 +1453,8 @@
wwo = &WOutDev[wDevID];
ARTS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
- val = wwo->dwPlayedTotal;
- TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
- lpTime->wType, wwo->format.wBitsPerSample,
- wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
- wwo->format.wf.nAvgBytesPerSec);
- TRACE("dwPlayedTotal=%lu\n", val);
-
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = val;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = round(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- default:
- FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- case TIME_MS:
- lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
}
/**************************************************************************
Index: dlls/winmm/wineaudioio/audio.c
===================================================================
RCS file: /var/cvs/wine/dlls/winmm/wineaudioio/audio.c,v
retrieving revision 1.13
diff -u -r1.13 audio.c
--- dlls/winmm/wineaudioio/audio.c 19 Jul 2004 20:08:06 -0000 1.13
+++ dlls/winmm/wineaudioio/audio.c 23 Jul 2004 00:51:06 -0000
@@ -185,6 +185,55 @@
static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid);
static DWORD widDsGuid(UINT wDevID, LPGUID pGuid);
+static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
+ PCMWAVEFORMAT* format)
+{
+ TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
+ lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
+ format->wf.nChannels, format->wf.nAvgBytesPerSec);
+ TRACE("Position in bytes=%lu\n", position);
+
+ switch (lpTime->wType) {
+ case TIME_SAMPLES:
+ lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
+ break;
+ case TIME_MS:
+ lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
+ TRACE("TIME_MS=%lu\n", lpTime->u.ms);
+ break;
+ case TIME_SMPTE:
+ position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
+ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
+ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
+ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
+ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
+ lpTime->u.smpte.fps = 30;
+ lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
+ if (position != 0)
+ {
+ /* Round up */
+ lpTime->u.smpte.frame++;
+ }
+ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
+ lpTime->u.smpte.hour, lpTime->u.smpte.min,
+ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
+ break;
+ default:
+ FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
+ lpTime->wType = TIME_BYTES;
+ /* fall through */
+ case TIME_BYTES:
+ lpTime->u.cb = position;
+ TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
/*======================================================================*
* Low level WAVE implementation *
*======================================================================*/
@@ -1082,8 +1131,6 @@
*/
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
- DWORD val;
WINE_WAVEOUT* wwo;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
@@ -1096,46 +1143,8 @@
if (lpTime == NULL) return MMSYSERR_INVALPARAM;
wwo = &WOutDev[wDevID];
- val = wwo->dwPlayedTotal;
-
- TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
- lpTime->wType, wwo->format.wBitsPerSample,
- wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
- wwo->format.wf.nAvgBytesPerSec);
- TRACE("dwTotalPlayed=%lu\n", val);
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = val;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = round(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- default:
- FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- case TIME_MS:
- lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
}
/**************************************************************************
@@ -2205,7 +2214,6 @@
*/
static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
WINE_WAVEIN* wwi;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
@@ -2218,46 +2226,7 @@
wwi = &WInDev[wDevID];
- TRACE("wType=%04X !\n", lpTime->wType);
- TRACE("wBitsPerSample=%u\n", wwi->format.wBitsPerSample);
- TRACE("nSamplesPerSec=%lu\n", wwi->format.wf.nSamplesPerSec);
- TRACE("nChannels=%u\n", wwi->format.wf.nChannels);
- TRACE("nAvgBytesPerSec=%lu\n", wwi->format.wf.nAvgBytesPerSec);
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = wwi->dwTotalRecorded;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = wwi->dwTotalRecorded * 8 /
- wwi->format.wBitsPerSample;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)wwi->dwTotalRecorded /
- (double)wwi->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = celi(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- case TIME_MS:
- lpTime->u.ms = wwi->dwTotalRecorded * 1000.0 /
- wwi->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- default:
- FIXME("format not supported (%u) ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, wwi->dwTotalRecorded, &wwi->format);
}
/**************************************************************************
Index: dlls/winmm/winejack/audio.c
===================================================================
RCS file: /var/cvs/wine/dlls/winmm/winejack/audio.c,v
retrieving revision 1.13
diff -u -r1.13 audio.c
--- dlls/winmm/winejack/audio.c 19 Jul 2004 20:08:06 -0000 1.13
+++ dlls/winmm/winejack/audio.c 23 Jul 2004 00:53:37 -0000
@@ -215,6 +215,55 @@
static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi);
#endif
+static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
+ PCMWAVEFORMAT* format)
+{
+ TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
+ lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
+ format->wf.nChannels, format->wf.nAvgBytesPerSec);
+ TRACE("Position in bytes=%lu\n", position);
+
+ switch (lpTime->wType) {
+ case TIME_SAMPLES:
+ lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
+ break;
+ case TIME_MS:
+ lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
+ TRACE("TIME_MS=%lu\n", lpTime->u.ms);
+ break;
+ case TIME_SMPTE:
+ position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
+ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
+ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
+ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
+ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
+ lpTime->u.smpte.fps = 30;
+ lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
+ if (position != 0)
+ {
+ /* Round up */
+ lpTime->u.smpte.frame++;
+ }
+ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
+ lpTime->u.smpte.hour, lpTime->u.smpte.min,
+ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
+ break;
+ default:
+ FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
+ lpTime->wType = TIME_BYTES;
+ /* fall through */
+ case TIME_BYTES:
+ lpTime->u.cb = position;
+ TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
/*======================================================================*
* Low level WAVE implementation *
@@ -1542,19 +1591,18 @@
*/
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
DWORD val;
WINE_WAVEOUT* wwo;
DWORD elapsedMS;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
-
+
if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
{
WARN("bad device ID !\n");
return MMSYSERR_BADDEVICEID;
}
-
+
/* if null pointer to time structure return error */
if (lpTime == NULL) return MMSYSERR_INVALPARAM;
@@ -1568,44 +1616,7 @@
/* account for the bytes played since the last JACK_Callback() */
val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
- TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
- lpTime->wType, wwo->format.wBitsPerSample,
- wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
- wwo->format.wf.nAvgBytesPerSec);
- TRACE("dwPlayedTotal=%lu\n", val);
-
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = val;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = round(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- default:
- FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- case TIME_MS:
- lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, val, &wwo->format);
}
/**************************************************************************
Index: dlls/winmm/winenas/audio.c
===================================================================
RCS file: /var/cvs/wine/dlls/winmm/winenas/audio.c,v
retrieving revision 1.15
diff -u -r1.15 audio.c
--- dlls/winmm/winenas/audio.c 19 Jul 2004 20:08:06 -0000 1.15
+++ dlls/winmm/winenas/audio.c 23 Jul 2004 00:56:04 -0000
@@ -279,6 +279,55 @@
return nas_states[state];
}
+static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
+ PCMWAVEFORMAT* format)
+{
+ TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
+ lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
+ format->wf.nChannels, format->wf.nAvgBytesPerSec);
+ TRACE("Position in bytes=%lu\n", position);
+
+ switch (lpTime->wType) {
+ case TIME_SAMPLES:
+ lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
+ break;
+ case TIME_MS:
+ lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
+ TRACE("TIME_MS=%lu\n", lpTime->u.ms);
+ break;
+ case TIME_SMPTE:
+ position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
+ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
+ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
+ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
+ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
+ lpTime->u.smpte.fps = 30;
+ lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
+ if (position != 0)
+ {
+ /* Round up */
+ lpTime->u.smpte.frame++;
+ }
+ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
+ lpTime->u.smpte.hour, lpTime->u.smpte.min,
+ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
+ break;
+ default:
+ FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
+ lpTime->wType = TIME_BYTES;
+ /* fall through */
+ case TIME_BYTES:
+ lpTime->u.cb = position;
+ TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
/*======================================================================*
* Low level WAVE implementation *
*======================================================================*/
@@ -1122,8 +1171,6 @@
*/
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
- DWORD val;
WINE_WAVEOUT* wwo;
TRACE("%u, %p, %lu);\n", wDevID, lpTime, uSize);
@@ -1140,46 +1187,8 @@
#if 0
NAS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
#endif
- val = wwo->WrittenTotal;
- TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
- lpTime->wType, wwo->format.wBitsPerSample,
- wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
- wwo->format.wf.nAvgBytesPerSec);
- TRACE("PlayedTotal=%lu\n", val);
-
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = val;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample / wwo->format.wf.nChannels;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = round(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- default:
- FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- case TIME_MS:
- lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, wwo->WrittenTotal, &wwo->format);
}
/**************************************************************************
Index: dlls/winmm/wineoss/audio.c
===================================================================
RCS file: /var/cvs/wine/dlls/winmm/wineoss/audio.c,v
retrieving revision 1.135
diff -u -r1.135 audio.c
--- dlls/winmm/wineoss/audio.c 19 Jul 2004 20:08:06 -0000 1.135
+++ dlls/winmm/wineoss/audio.c 22 Jul 2004 14:49:26 -0000
@@ -323,6 +323,55 @@
return MMSYSERR_INVALPARAM;
}
+static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
+ PCMWAVEFORMAT* format)
+{
+ TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
+ lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
+ format->wf.nChannels, format->wf.nAvgBytesPerSec);
+ TRACE("Position in bytes=%lu\n", position);
+
+ switch (lpTime->wType) {
+ case TIME_SAMPLES:
+ lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
+ break;
+ case TIME_MS:
+ lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
+ TRACE("TIME_MS=%lu\n", lpTime->u.ms);
+ break;
+ case TIME_SMPTE:
+ position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
+ lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
+ lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
+ lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
+ lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
+ lpTime->u.smpte.fps = 30;
+ lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
+ position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
+ if (position != 0)
+ {
+ /* Round up */
+ lpTime->u.smpte.frame++;
+ }
+ TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
+ lpTime->u.smpte.hour, lpTime->u.smpte.min,
+ lpTime->u.smpte.sec, lpTime->u.smpte.frame);
+ break;
+ default:
+ FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
+ lpTime->wType = TIME_BYTES;
+ /* fall through */
+ case TIME_BYTES:
+ lpTime->u.cb = position;
+ TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
+ break;
+ }
+ return MMSYSERR_NOERROR;
+}
+
/*======================================================================*
* Low level WAVE implementation *
*======================================================================*/
@@ -2077,8 +2126,6 @@
*/
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
- DWORD val;
WINE_WAVEOUT* wwo;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
@@ -2098,46 +2145,8 @@
if (wwo->ossdev->out_caps.dwSupport & WAVECAPS_SAMPLEACCURATE)
OSS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
#endif
- val = wwo->dwPlayedTotal;
- TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
- lpTime->wType, wwo->format.wBitsPerSample,
- wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
- wwo->format.wf.nAvgBytesPerSec);
- TRACE("dwPlayedTotal=%lu\n", val);
-
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = val;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = round(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- default:
- FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- case TIME_MS:
- lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
}
/**************************************************************************
@@ -3867,7 +3881,6 @@
*/
static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{
- double time;
WINE_WAVEIN* wwi;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
@@ -3885,50 +3898,10 @@
wwi = &WInDev[wDevID];
#ifdef EXACT_WIDPOSITION
if (wwi->ossdev->in_caps_support & WAVECAPS_SAMPLEACCURATE)
- OSS_AddRingMessage(&(wwi->msgRing), WINE_WM_UPDATE, 0, TRUE);
+ OSS_AddRingMessage(&(wwi->msgRing), WINE_WM_UPDATE, 0, TRUE);
#endif
- TRACE("wType=%04X !\n", lpTime->wType);
- TRACE("wBitsPerSample=%u\n", wwi->format.wBitsPerSample);
- TRACE("nSamplesPerSec=%lu\n", wwi->format.wf.nSamplesPerSec);
- TRACE("nChannels=%u\n", wwi->format.wf.nChannels);
- TRACE("nAvgBytesPerSec=%lu\n", wwi->format.wf.nAvgBytesPerSec);
- TRACE("dwTotalRecorded=%lu\n",wwi->dwTotalRecorded);
- switch (lpTime->wType) {
- case TIME_BYTES:
- lpTime->u.cb = wwi->dwTotalRecorded;
- TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
- break;
- case TIME_SAMPLES:
- lpTime->u.sample = wwi->dwTotalRecorded * 8 /
- wwi->format.wBitsPerSample / wwi->format.wf.nChannels;
- TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
- break;
- case TIME_SMPTE:
- time = (double)wwi->dwTotalRecorded /
- (double)wwi->format.wf.nAvgBytesPerSec;
- lpTime->u.smpte.hour = time / (60 * 60);
- time -= lpTime->u.smpte.hour * (60 * 60);
- lpTime->u.smpte.min = time / 60;
- time -= lpTime->u.smpte.min * 60;
- lpTime->u.smpte.sec = time;
- time -= lpTime->u.smpte.sec;
- lpTime->u.smpte.frame = ceil(time * 30);
- lpTime->u.smpte.fps = 30;
- TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
- lpTime->u.smpte.hour, lpTime->u.smpte.min,
- lpTime->u.smpte.sec, lpTime->u.smpte.frame);
- break;
- default:
- FIXME("format not supported (%u) ! use TIME_MS !\n", lpTime->wType);
- lpTime->wType = TIME_MS;
- case TIME_MS:
- lpTime->u.ms = wwi->dwTotalRecorded * 1000.0 /
- wwi->format.wf.nAvgBytesPerSec;
- TRACE("TIME_MS=%lu\n", lpTime->u.ms);
- break;
- }
- return MMSYSERR_NOERROR;
+ return bytes_to_mmtime(lpTime, wwi->dwTotalRecorded, &wwi->format);
}
/**************************************************************************
More information about the wine-patches
mailing list