Commit 99b0e8fa authored by Robert Reif's avatar Robert Reif Committed by Alexandre Julliard

Added volume and pan support to primary buffers.

Added more property set support.
parent 6f7cbc08
......@@ -1140,6 +1140,8 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown
(*ippDS)->drvcaps.dwPrimaryBuffers = 1;
}
(*ippDS)->volpan.lVolume = 0;
(*ippDS)->volpan.lPan = 0;
DSOUND_RecalcVolPan(&((*ippDS)->volpan));
InitializeCriticalSection(&((*ippDS)->mixlock));
......
......@@ -55,14 +55,14 @@ void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan)
TRACE("(%p)\n",volpan);
/* the AmpFactors are expressed in 16.16 fixed point */
volpan->dwVolAmpFactor = (ULONG) (pow(2.0, volpan->lVolume / 600.0) * 65536);
volpan->dwVolAmpFactor = (ULONG) (pow(2.0, volpan->lVolume / 600.0) * 0xffff);
/* FIXME: dwPan{Left|Right}AmpFactor */
/* FIXME: use calculated vol and pan ampfactors */
temp = (double) (volpan->lVolume - (volpan->lPan > 0 ? volpan->lPan : 0));
volpan->dwTotalLeftAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 65536);
volpan->dwTotalLeftAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 0xffff);
temp = (double) (volpan->lVolume + (volpan->lPan < 0 ? volpan->lPan : 0));
volpan->dwTotalRightAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 65536);
volpan->dwTotalRightAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 0xffff);
TRACE("left = %lx, right = %lx\n", volpan->dwTotalLeftAmpFactor, volpan->dwTotalRightAmpFactor);
}
......
......@@ -74,6 +74,8 @@ static HRESULT DSOUND_PrimaryOpen(IDirectSoundImpl *This)
HRESULT err = DS_OK;
TRACE("(%p)\n",This);
DSOUND_RecalcVolPan(&(This->volpan));
/* are we using waveOut stuff? */
if (!This->hwbuf) {
LPBYTE newbuf;
......@@ -128,7 +130,15 @@ static HRESULT DSOUND_PrimaryOpen(IDirectSoundImpl *This)
}
if ((err == DS_OK) && (merr != DS_OK))
err = merr;
if (!err) {
DWORD vol = (This->volpan.dwTotalLeftAmpFactor & 0xffff) | (This->volpan.dwTotalRightAmpFactor << 16);
err = mmErr(waveOutSetVolume(This->hwo, vol));
}
} else {
err = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
}
return err;
}
......@@ -431,7 +441,6 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
TRACE("(%p,%ld)\n",This,vol);
/* I'm not sure if we need this for primary buffer */
if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
......@@ -458,15 +467,9 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
WARN("IDsDriverBuffer_SetVolumePan failed\n");
return hres;
}
}
else {
#if 0 /* should we really do this? */
/* the DS volume ranges from 0 (max, 0dB attenuation) to -10000 (min, 100dB attenuation) */
/* the MM volume ranges from 0 to 0xffff in an unspecified logarithmic scale */
WORD cvol = 0xffff + vol*6 + vol/2;
DWORD vol = cvol | ((DWORD)cvol << 16)
} else {
DWORD vol = (dsound->volpan.dwTotalLeftAmpFactor & 0xffff) | (dsound->volpan.dwTotalRightAmpFactor << 16);
waveOutSetVolume(dsound->hwo, vol);
#endif
}
}
......@@ -778,13 +781,8 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan(
}
}
else {
#if 0 /* should we really do this? */
/* the DS volume ranges from 0 (max, 0dB attenuation) to -10000 (min, 100dB attenuation) */
/* the MM volume ranges from 0 to 0xffff in an unspecified logarithmic scale */
WORD cvol = 0xffff + vol*6 + vol/2;
DWORD vol = cvol | ((DWORD)cvol << 16)
DWORD vol = (dsound->volpan.dwTotalLeftAmpFactor & 0xffff) | (dsound->volpan.dwTotalRightAmpFactor << 16);
waveOutSetVolume(dsound->hwo, vol);
#endif
}
}
......
......@@ -431,8 +431,47 @@ static HRESULT WINAPI DSPROPERTY_Description1(
}
}
} else {
FIXME("DeviceId=Unknown\n");
return E_PROP_ID_UNSUPPORTED;
BOOL found = FALSE;
ULONG wod;
int wodn;
/* given specific device so try the render devices first */
wodn = waveOutGetNumDevs();
for (wod = 0; wod < wodn; wod++) {
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
if (err == DS_OK) {
if (IsEqualGUID( &ppd->DeviceId, &guid) ) {
DSDRIVERDESC desc;
TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
ppd->WaveDeviceId = wod;
ppd->Devnode = wod;
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
if (err == DS_OK) {
PIDSDRIVER drv = NULL;
strncpy(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA) - 1);
strncpy(ppd->ModuleA, desc.szDrvName, sizeof(ppd->ModuleA) - 1);
MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) );
err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
if (err == DS_OK && drv)
ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
found = TRUE;
break;
} else {
WARN("waveOutMessage failed\n");
return E_PROP_ID_UNSUPPORTED;
}
}
} else {
WARN("waveOutMessage failed\n");
return E_PROP_ID_UNSUPPORTED;
}
}
if (found == FALSE) {
WARN("device not found\n");
return E_PROP_ID_UNSUPPORTED;
}
}
if (pcbReturned) {
......
......@@ -254,7 +254,8 @@ STOP:
}
static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
int is_primary, int play, int buffer3d,
int is_primary, BOOL set_volume, LONG volume,
BOOL set_pan, LONG pan, int play, int buffer3d,
LPDIRECTSOUND3DLISTENER listener,
int move_listener, int move_sound)
{
......@@ -358,7 +359,7 @@ static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
if (play) {
play_state_t state;
LONG volume,pan;
LPDIRECTSOUND3DBUFFER buffer=NULL;
DS3DBUFFER buffer_param;
DS3DLISTENER listener_param;
......@@ -417,34 +418,50 @@ static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
}
if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_SetVolume(dsbo,-300);
if (set_volume) {
rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
trace(" volume=%ld\n",volume);
} else {
/* DSOUND: Error: Buffer does not have CTRLVOLUME */
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc);
if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_SetVolume(dsbo,-300);
ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
trace(" volume=%ld\n",volume);
} else {
/* DSOUND: Error: Buffer does not have CTRLVOLUME */
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc);
}
}
if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_SetPan(dsbo,0);
if (set_pan) {
rc=IDirectSoundBuffer_SetPan(dsbo,pan);
ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
trace(" pan=%ld\n",pan);
} else {
/* DSOUND: Error: Buffer does not have CTRLPAN */
rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc);
if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_SetPan(dsbo,0);
ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
trace(" pan=%ld\n",pan);
} else {
/* DSOUND: Error: Buffer does not have CTRLPAN */
rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc);
}
}
state.wave=wave_generate_la(&wfx,((double)TONE_DURATION)/1000,&state.wave_len);
......@@ -639,7 +656,7 @@ static HRESULT test_secondary(LPGUID lpGuid, int play,
}
if (rc==DS_OK&&secondary!=NULL) {
test_buffer(dso,secondary,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound);
test_buffer(dso,secondary,0,FALSE,0,FALSE,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound);
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
}
......@@ -768,7 +785,7 @@ static HRESULT test_primary(LPGUID lpGuid)
LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
DSBUFFERDESC bufdesc;
DSCAPS dscaps;
int ref;
int ref, i;
/* Create the DirectSound object */
rc=DirectSoundCreate(lpGuid,&dso,NULL);
......@@ -829,7 +846,22 @@ static HRESULT test_primary(LPGUID lpGuid)
rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
/* rc=0x88780032 */
ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer primary buffer should have failed 0x%lx\n",rc);
test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
test_buffer(dso,primary,1,TRUE,0,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
if (winetest_interactive) {
LONG volume = DSBVOLUME_MAX;
for (i = 0; i < 6; i++) {
test_buffer(dso,primary,1,TRUE,volume,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
}
if (winetest_interactive) {
LONG pan = DSBPAN_LEFT;
for (i = 0; i < 7; i++) {
test_buffer(dso,primary,1,TRUE,0,TRUE,pan,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
}
}
}
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
}
......@@ -894,7 +926,7 @@ static HRESULT test_primary_3d(LPGUID lpGuid)
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
if (rc==DS_OK&&primary!=NULL) {
test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
}
......@@ -971,7 +1003,7 @@ static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
/* Testing the buffer */
test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0);
test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0);
}
/* Testing the reference counting */
......
......@@ -1891,7 +1891,10 @@ static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
right = (HIWORD(dwParam) * 100) / 0xFFFFl;
volume = left + (right << 8);
if (wDevID >= numOutDev) return MMSYSERR_INVALPARAM;
if (wDevID >= numOutDev) {
WARN("invalid parameter: wDevID > %d\n", numOutDev);
return MMSYSERR_INVALPARAM;
}
if ((mixer = open(WOutDev[wDevID].ossdev->mixer_name, O_WRONLY|O_NDELAY)) < 0) {
WARN("mixer device not available !\n");
......@@ -2138,9 +2141,17 @@ static HRESULT WINAPI IDsDriverBufferImpl_SetFrequency(PIDSDRIVERBUFFER iface, D
static HRESULT WINAPI IDsDriverBufferImpl_SetVolumePan(PIDSDRIVERBUFFER iface, PDSVOLUMEPAN pVolPan)
{
/* ICOM_THIS(IDsDriverBufferImpl,iface); */
FIXME("(%p,%p): stub!\n",iface,pVolPan);
/* FIXME: the dsound software mixer does this for us so don't return an error */
DWORD vol;
ICOM_THIS(IDsDriverBufferImpl,iface);
TRACE("(%p,%p)\n",This,pVolPan);
vol = pVolPan->dwTotalLeftAmpFactor | (pVolPan->dwTotalRightAmpFactor << 16);
if (wodSetVolume(This->drv->wDevID, vol) != MMSYSERR_NOERROR) {
WARN("wodSetVolume failed\n");
return DSERR_INVALIDPARAM;
}
return DS_OK;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment