wineoss WAVEFORMATEXTENSIBLE support
Robert Reif
reif at earthlink.net
Sun Aug 15 16:24:14 CDT 2004
Adds WAVEFORMATEXTENSIBLE support.
This patch does not add any support for the new features available
when using WAVEFORMATEXTENSIBLE. It only allows
the new (and recommended for new development) way of specifying
a format.
-------------- next part --------------
Index: dlls/winmm/wineoss/audio.c
===================================================================
RCS file: /home/wine/wine/dlls/winmm/wineoss/audio.c,v
retrieving revision 1.140
diff -u -r1.140 audio.c
--- dlls/winmm/wineoss/audio.c 13 Aug 2004 19:42:36 -0000 1.140
+++ dlls/winmm/wineoss/audio.c 15 Aug 2004 21:20:37 -0000
@@ -65,8 +65,12 @@
#include "winerror.h"
#include "wine/winuser16.h"
#include "mmddk.h"
+#include "mmreg.h"
#include "dsound.h"
#include "dsdriver.h"
+#include "ks.h"
+#include "ksguid.h"
+#include "ksmedia.h"
#include "oss.h"
#include "wine/debug.h"
@@ -180,7 +184,7 @@
volatile int state; /* one of the WINE_WS_ manifest constants */
WAVEOPENDESC waveDesc;
WORD wFlags;
- PCMWAVEFORMAT format;
+ WAVEFORMATPCMEX waveFormat;
DWORD volume;
/* OSS information */
@@ -210,7 +214,7 @@
DWORD dwFragmentSize; /* OpenSound '/dev/dsp' give us that size */
WAVEOPENDESC waveDesc;
WORD wFlags;
- PCMWAVEFORMAT format;
+ WAVEFORMATPCMEX waveFormat;
LPWAVEHDR lpQueuePtr;
DWORD dwTotalRecorded;
DWORD dwTotalRead;
@@ -324,33 +328,33 @@
}
static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
- PCMWAVEFORMAT* format)
+ WAVEFORMATPCMEX* 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);
+ lpTime->wType, format->Format.wBitsPerSample, format->Format.nSamplesPerSec,
+ format->Format.nChannels, format->Format.nAvgBytesPerSec);
TRACE("Position in bytes=%lu\n", position);
switch (lpTime->wType) {
case TIME_SAMPLES:
- lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+ lpTime->u.sample = position / (format->Format.wBitsPerSample / 8 * format->Format.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);
+ lpTime->u.ms = 1000.0 * position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels * format->Format.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;
+ position = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels);
+ lpTime->u.smpte.sec = position / format->Format.nSamplesPerSec;
+ position -= lpTime->u.smpte.sec * format->Format.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;
+ lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->Format.nSamplesPerSec;
+ position -= lpTime->u.smpte.frame * format->Format.nSamplesPerSec / lpTime->u.smpte.fps;
if (position != 0)
{
/* Round up */
@@ -372,6 +376,47 @@
return MMSYSERR_NOERROR;
}
+static BOOL supportedFormat(LPWAVEFORMATEX wf)
+{
+ TRACE("(%p)\n",wf);
+
+ if (wf->nSamplesPerSec<DSBFREQUENCY_MIN||wf->nSamplesPerSec>DSBFREQUENCY_MAX)
+ return FALSE;
+
+ if (wf->wFormatTag == WAVE_FORMAT_PCM) {
+ if (wf->nChannels==1||wf->nChannels==2) {
+ if (wf->wBitsPerSample==8||wf->wBitsPerSample==16) {
+ return TRUE;
+ }
+ }
+ }
+ else if (wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
+ WAVEFORMATEXTENSIBLE * wfex = (WAVEFORMATEXTENSIBLE *)wf;
+ if (wf->cbSize == 22 && IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
+ if (wf->nChannels==1||wf->nChannels==2) {
+ if ((wf->wBitsPerSample==8||wf->wBitsPerSample==16) &&
+ (wfex->Samples.wValidBitsPerSample==8||wfex->Samples.wValidBitsPerSample==16)) {
+ FIXME("WAVE_FORMAT_EXTENSIBLE not fully supported\n");
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static void copy_format(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2)
+{
+ ZeroMemory(wf2, sizeof(wf2));
+ if (wf1->wFormatTag == WAVE_FORMAT_PCM)
+ memcpy(wf2, wf1, sizeof(PCMWAVEFORMAT));
+ else if (wf1->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
+ memcpy(wf2, wf1, sizeof(WAVEFORMATPCMEX));
+ else
+ memcpy(wf2, wf1, sizeof(WAVEFORMATEX) + wf1->cbSize);
+}
+
/*======================================================================*
* Low level WAVE implementation *
*======================================================================*/
@@ -1425,7 +1470,7 @@
static DWORD wodPlayer_DSPWait(const WINE_WAVEOUT *wwo)
{
/* time for one fragment to be played */
- return wwo->dwFragmentSize * 1000 / wwo->format.wf.nAvgBytesPerSec;
+ return wwo->dwFragmentSize * 1000 / wwo->waveFormat.Format.nAvgBytesPerSec;
}
/**************************************************************************
@@ -1442,7 +1487,7 @@
if (lpWaveHdr->reserved < wwo->dwPlayedTotal) {
dwMillis = 1;
} else {
- dwMillis = (lpWaveHdr->reserved - wwo->dwPlayedTotal) * 1000 / wwo->format.wf.nAvgBytesPerSec;
+ dwMillis = (lpWaveHdr->reserved - wwo->dwPlayedTotal) * 1000 / wwo->waveFormat.Format.nAvgBytesPerSec;
if (!dwMillis) dwMillis = 1;
}
@@ -1810,10 +1855,7 @@
}
/* only PCM format is supported so far... */
- if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
- lpDesc->lpFormat->nChannels == 0 ||
- lpDesc->lpFormat->nSamplesPerSec == 0 ||
- (lpDesc->lpFormat->wBitsPerSample!=8 && lpDesc->lpFormat->wBitsPerSample!=16)) {
+ if (!supportedFormat(lpDesc->lpFormat)) {
WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
lpDesc->lpFormat->nSamplesPerSec);
@@ -1895,15 +1937,15 @@
wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
- memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
- memcpy(&wwo->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
+ memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
+ copy_format(lpDesc->lpFormat, &wwo->waveFormat);
- if (wwo->format.wBitsPerSample == 0) {
+ if (wwo->waveFormat.Format.wBitsPerSample == 0) {
WARN("Resetting zeroed wBitsPerSample\n");
- wwo->format.wBitsPerSample = 8 *
- (wwo->format.wf.nAvgBytesPerSec /
- wwo->format.wf.nSamplesPerSec) /
- wwo->format.wf.nChannels;
+ wwo->waveFormat.Format.wBitsPerSample = 8 *
+ (wwo->waveFormat.Format.nAvgBytesPerSec /
+ wwo->waveFormat.Format.nSamplesPerSec) /
+ wwo->waveFormat.Format.nChannels;
}
/* Read output space info for future reference */
if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
@@ -1935,14 +1977,14 @@
TRACE("fd=%d fragstotal=%d fragsize=%d BufferSize=%ld\n",
wwo->ossdev->fd, info.fragstotal, info.fragsize, wwo->dwBufferSize);
- if (wwo->dwFragmentSize % wwo->format.wf.nBlockAlign) {
- ERR("Fragment doesn't contain an integral number of data blocks fragsize=%ld BlockAlign=%d\n",wwo->dwFragmentSize,wwo->format.wf.nBlockAlign);
+ if (wwo->dwFragmentSize % wwo->waveFormat.Format.nBlockAlign) {
+ ERR("Fragment doesn't contain an integral number of data blocks fragsize=%ld BlockAlign=%d\n",wwo->dwFragmentSize,wwo->waveFormat.Format.nBlockAlign);
/* Some SoundBlaster 16 cards return an incorrect (odd) fragment
* size for 16 bit sound. This will cause a system crash when we try
* to write just the specified odd number of bytes. So if we
* detect something is wrong we'd better fix it.
*/
- wwo->dwFragmentSize-=wwo->dwFragmentSize % wwo->format.wf.nBlockAlign;
+ wwo->dwFragmentSize-=wwo->dwFragmentSize % wwo->waveFormat.Format.nBlockAlign;
}
OSS_InitRingMessage(&wwo->msgRing);
@@ -1954,9 +1996,9 @@
wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
- wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
- wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
- wwo->format.wf.nBlockAlign);
+ wwo->waveFormat.Format.wBitsPerSample, wwo->waveFormat.Format.nAvgBytesPerSec,
+ wwo->waveFormat.Format.nSamplesPerSec, wwo->waveFormat.Format.nChannels,
+ wwo->waveFormat.Format.nBlockAlign);
return wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
}
@@ -2019,10 +2061,10 @@
lpWaveHdr->dwFlags |= WHDR_INQUEUE;
lpWaveHdr->lpNext = 0;
- if ((lpWaveHdr->dwBufferLength & (WOutDev[wDevID].format.wf.nBlockAlign - 1)) != 0)
+ if ((lpWaveHdr->dwBufferLength & (WOutDev[wDevID].waveFormat.Format.nBlockAlign - 1)) != 0)
{
- WARN("WaveHdr length isn't a multiple of the PCM block size: %ld %% %d\n",lpWaveHdr->dwBufferLength,WOutDev[wDevID].format.wf.nBlockAlign);
- lpWaveHdr->dwBufferLength &= ~(WOutDev[wDevID].format.wf.nBlockAlign - 1);
+ WARN("WaveHdr length isn't a multiple of the PCM block size: %ld %% %d\n",lpWaveHdr->dwBufferLength,WOutDev[wDevID].waveFormat.Format.nBlockAlign);
+ lpWaveHdr->dwBufferLength &= ~(WOutDev[wDevID].waveFormat.Format.nBlockAlign - 1);
}
OSS_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);
@@ -2152,7 +2194,7 @@
OSS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
#endif
- return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
+ return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->waveFormat);
}
/**************************************************************************
@@ -2353,7 +2395,7 @@
/* IDsDriverBufferImpl fields */
IDsDriverImpl* drv;
DWORD buflen;
- WAVEFORMATEX wfx;
+ WAVEFORMATPCMEX wfex;
LPBYTE mapping;
DWORD maplen;
int fd;
@@ -2572,8 +2614,8 @@
static HRESULT DSDB_MapBuffer(IDsDriverBufferImpl *dsdb)
{
- TRACE("(%p), format=%ldx%dx%d\n", dsdb, dsdb->wfx.nSamplesPerSec,
- dsdb->wfx.wBitsPerSample, dsdb->wfx.nChannels);
+ TRACE("(%p), format=%ldx%dx%d\n", dsdb, dsdb->wfex.Format.nSamplesPerSec,
+ dsdb->wfex.Format.wBitsPerSample, dsdb->wfex.Format.nChannels);
if (!dsdb->mapping) {
dsdb->mapping = mmap(NULL, dsdb->maplen, PROT_WRITE, MAP_SHARED,
dsdb->fd, 0);
@@ -2593,8 +2635,8 @@
{
unsigned char* p1 = dsdb->mapping;
unsigned len = dsdb->maplen;
- unsigned char silence = (dsdb->wfx.wBitsPerSample == 8) ? 128 : 0;
- unsigned long ulsilence = (dsdb->wfx.wBitsPerSample == 8) ? 0x80808080 : 0;
+ unsigned char silence = (dsdb->wfex.Format.wBitsPerSample == 8) ? 128 : 0;
+ unsigned long ulsilence = (dsdb->wfex.Format.wBitsPerSample == 8) ? 0x80808080 : 0;
if (len >= 16) /* so we can have at least a 4 long area to store... */
{
@@ -3022,7 +3064,7 @@
(*ippdsdb)->lpVtbl = &dsdbvt;
(*ippdsdb)->ref = 1;
(*ippdsdb)->drv = This;
- (*ippdsdb)->wfx = *pwfx;
+ copy_format(pwfx, &(*ippdsdb)->wfex);
(*ippdsdb)->fd = WOutDev[This->wDevID].ossdev->fd;
(*ippdsdb)->dwFlags = dwFlags;
@@ -3320,7 +3362,7 @@
read(wwi->ossdev->fd, &xs, 4);
/* make sleep time to be # of ms to output a fragment */
- dwSleepTime = (wwi->dwFragmentSize * 1000) / wwi->format.wf.nAvgBytesPerSec;
+ dwSleepTime = (wwi->dwFragmentSize * 1000) / wwi->waveFormat.Format.nAvgBytesPerSec;
TRACE("sleeptime=%ld ms\n", dwSleepTime);
for (;;) {
@@ -3620,10 +3662,7 @@
}
/* only PCM format is supported so far... */
- if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
- lpDesc->lpFormat->nChannels == 0 ||
- lpDesc->lpFormat->nSamplesPerSec == 0 ||
- (lpDesc->lpFormat->wBitsPerSample!=8 && lpDesc->lpFormat->wBitsPerSample!=16)) {
+ if (!supportedFormat(lpDesc->lpFormat)) {
WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
lpDesc->lpFormat->nSamplesPerSec);
@@ -3697,15 +3736,15 @@
wwi->dwTotalRead = 0;
wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
- memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
- memcpy(&wwi->format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
+ memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
+ copy_format(lpDesc->lpFormat, &wwi->waveFormat);
- if (wwi->format.wBitsPerSample == 0) {
+ if (wwi->waveFormat.Format.wBitsPerSample == 0) {
WARN("Resetting zeroed wBitsPerSample\n");
- wwi->format.wBitsPerSample = 8 *
- (wwi->format.wf.nAvgBytesPerSec /
- wwi->format.wf.nSamplesPerSec) /
- wwi->format.wf.nChannels;
+ wwi->waveFormat.Format.wBitsPerSample = 8 *
+ (wwi->waveFormat.Format.nAvgBytesPerSec /
+ wwi->waveFormat.Format.nSamplesPerSec) /
+ wwi->waveFormat.Format.nChannels;
}
if (ioctl(wwi->ossdev->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
@@ -3725,9 +3764,9 @@
TRACE("dwFragmentSize=%lu\n", wwi->dwFragmentSize);
TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
- wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
- wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
- wwi->format.wf.nBlockAlign);
+ wwi->waveFormat.Format.wBitsPerSample, wwi->waveFormat.Format.nAvgBytesPerSec,
+ wwi->waveFormat.Format.nSamplesPerSec, wwi->waveFormat.Format.nChannels,
+ wwi->waveFormat.Format.nBlockAlign);
OSS_InitRingMessage(&wwi->msgRing);
@@ -3903,7 +3942,7 @@
OSS_AddRingMessage(&(wwi->msgRing), WINE_WM_UPDATE, 0, TRUE);
#endif
- return bytes_to_mmtime(lpTime, wwi->dwTotalRecorded, &wwi->format);
+ return bytes_to_mmtime(lpTime, wwi->dwTotalRecorded, &wwi->waveFormat);
}
/**************************************************************************
More information about the wine-patches
mailing list