Пример #1
0
Файл: ds.c Проект: btb/d2x
void SSGetCaps(SSCaps *caps)
{
	DSCAPS dscaps;

	dscaps.dwSize = sizeof(DSCAPS);
	IDirectSound_GetCaps(SSMixer.lpds, &dscaps);
	
	if ((dscaps.dwFlags&DSCAPS_SECONDARY16BIT)) caps->bits_per_sample = 16;
	else caps->bits_per_sample = 8;

	caps->sample_rate = dscaps.dwMaxSecondarySampleRate;
}
Пример #2
0
int I2_Init()
{
    DSBUFFERDESC        desc;
    LPDIRECTSOUNDBUFFER bufTemp;

    if(initOk) return true; // Don't init a second time.
    if(FAILED(hr = EAXDirectSoundCreate(NULL, &dsound, NULL)))
    {
        // EAX can't be initialized. Use normal DS, then.
        ST_Message("I2_Init: EAX 2 couldn't be initialized (result: %i).\n", hr & 0xffff);
        if(FAILED(hr = DirectSoundCreate(NULL, &dsound, NULL)))
        {
            ST_Message("I2_Init: Couldn't create dsound (result: %i).\n", hr & 0xffff);
            return false;
        }
    }
    // Set the cooperative level.
    if(FAILED(hr = IDirectSound_SetCooperativeLevel(dsound, hWndMain, DSSCL_PRIORITY)))
    {
        ST_Message("I2_Init: Couldn't set dSound cooperative level (result: %i).\n", hr & 0xffff);
        return false;
    }
    // Get the listener.
    memset(&desc, 0, sizeof(desc));
    desc.dwSize = sizeof(desc);
    desc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
    if(SUCCEEDED(IDirectSound_CreateSoundBuffer(dsound, &desc, &bufTemp, NULL)))
    {
        // Query the listener interface.
        IDirectSoundBuffer_QueryInterface(bufTemp, &IID_IDirectSound3DListener, &dsListener);
    }
    // Release the primary buffer interface, we won't need it.
    IDirectSoundBuffer_Release(bufTemp);

    // Try to get the EAX listener property set. Create a temporary secondary buffer for it.
    if(SUCCEEDED( createDSBuffer(DSBCAPS_STATIC | DSBCAPS_CTRL3D, DSBSIZE_MIN, 22050, 8, 1, &bufTemp) ))
    {
        // Now try to get the property set.
        if(SUCCEEDED(hr = IDirectSoundBuffer_QueryInterface(bufTemp,
            &IID_IKsPropertySet, &eaxListener)))
        {
            DWORD support = 0, revsize = 0;
            // Check for support.
            if(FAILED(hr = IKsPropertySet_QuerySupport(eaxListener,
                &DSPROPSETID_EAX_ListenerProperties,
                DSPROPERTY_EAXLISTENER_ENVIRONMENT,
                &support))
                || ((support & NEEDED_SUPPORT) != NEEDED_SUPPORT))
            {
                ST_Message("I2_Init: Property set acquired, but EAX 2 not supported.\n  Result:%i, support:%x\n", hr&0xffff, support);
                IKsPropertySet_Release(eaxListener);
                eaxListener = NULL;
            }
            else
            {
                // EAX is supported!
                ST_Message("I2_Init: EAX 2 available.\n");
            }
        }
        // Release the temporary buffer interface.
        IDirectSoundBuffer_Release(bufTemp);
    }

    // Get the caps.
    dsCaps.dwSize = sizeof(dsCaps);
    IDirectSound_GetCaps(dsound, &dsCaps);
    ST_Message("I2_Init: Number of hardware 3D buffers: %i\n", dsCaps.dwMaxHw3DAllBuffers);

    // Configure the DS3D listener.
    if(dsListener)
    {
        IDirectSound3DListener_SetDistanceFactor(dsListener, 1/36.0f, DS3D_DEFERRED);
        IDirectSound3DListener_SetDopplerFactor(dsListener, 2, DS3D_DEFERRED);
    }

    // Success!
    initOk = true;
    return true;
}
Пример #3
0
int DSSetupSound()
{
	HRESULT dsval;
	WAVEFORMATEX pcmwf;

	dsval = DirectSoundCreate(NULL,&lpDS,NULL);
	if(dsval != DS_OK)
	{
		MessageBox(hWMain,"DirectSoundCreate!","Error",MB_OK);
		return -1;
	}

	if(DS_OK != IDirectSound_SetCooperativeLevel(lpDS,hWMain, DSSCL_PRIORITY))
	{
		if(DS_OK != IDirectSound_SetCooperativeLevel(lpDS,hWMain, DSSCL_NORMAL))
		{
			MessageBox(hWMain,"SetCooperativeLevel!","Error",MB_OK);
			return -1;
		}
	}

	memset(&dsbd,0,sizeof(DSBUFFERDESC));
	dsbd.dwSize = sizeof(DSBUFFERDESC);                                     // NT4 hack! sizeof(dsbd);
	dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
	dsbd.dwBufferBytes = 0;
	dsbd.lpwfxFormat = NULL;

	dsval = IDirectSound_CreateSoundBuffer(lpDS,&dsbd,&lpDSBPRIMARY,NULL);
	if(dsval != DS_OK)
	{
		MessageBox(hWMain, "CreateSoundBuffer (Primary)", "Error",MB_OK);
		return -1;
	}

	memset(&pcmwf, 0, sizeof(WAVEFORMATEX));
	pcmwf.wFormatTag = WAVE_FORMAT_PCM;

	pcmwf.nChannels = 2;
	pcmwf.nBlockAlign = 4;

	pcmwf.nSamplesPerSec = SAMPLE_RATE;

	pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
	pcmwf.wBitsPerSample = 16;

	dsval = IDirectSoundBuffer_SetFormat(lpDSBPRIMARY,&pcmwf);
	if(dsval != DS_OK)
	{
		MessageBox(hWMain, "SetFormat!", "Error",MB_OK);
		return -1;
	}

	dscaps.dwSize = sizeof(DSCAPS);
	dsbcaps.dwSize = sizeof(DSBCAPS);
	IDirectSound_GetCaps(lpDS,&dscaps);
	IDirectSoundBuffer_GetCaps(lpDSBPRIMARY,&dsbcaps);

	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
	// NT4 hack! sizeof(DSBUFFERDESC);
	dsbdesc.dwSize = sizeof(DSBUFFERDESC);
	dsbdesc.dwFlags = DSBCAPS_LOCHARDWARE | DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
	dsbdesc.dwBufferBytes = SOUNDSIZE;
	dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;

	dsval = IDirectSound_CreateSoundBuffer(lpDS,&dsbdesc,&lpDSBSECONDARY1,NULL);
	if(dsval != DS_OK)
	{
		dsbdesc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
		dsval = IDirectSound_CreateSoundBuffer(lpDS,&dsbdesc,&lpDSBSECONDARY1,NULL);
		if(dsval != DS_OK)
		{
			MessageBox(hWMain,"CreateSoundBuffer (Secondary1)", "Error",MB_OK);
			return -1;
		}
	}

	dsval = IDirectSoundBuffer_Play(lpDSBPRIMARY,0,0,DSBPLAY_LOOPING);
	if(dsval != DS_OK)
	{
		MessageBox(hWMain,"Play (Primary)","Error",MB_OK);
		return -1;
	}

	dsval = IDirectSoundBuffer_Play(lpDSBSECONDARY1,0,0,DSBPLAY_LOOPING);
	if(dsval != DS_OK)
	{
		MessageBox(hWMain,"Play (Secondary1)","Error",MB_OK);
		return -1;
	}

	// init some play vars
	LastWrite = 0x00000000;
	LastPlay = 0;

	return 0;
}
Пример #4
0
static HRESULT test_frequency(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND dso=NULL;
    LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
    DSBUFFERDESC bufdesc;
    DSCAPS dscaps;
    WAVEFORMATEX wfx, wfx1;
    DWORD f, r;
    int ref;
    int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
                    48000, 96000 };

    /* Create the DirectSound object */
    rc=DirectSoundCreate(lpGuid,&dso,NULL);
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
       "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
    if (rc!=DS_OK)
        return rc;

    /* Get the device capabilities */
    ZeroMemory(&dscaps, sizeof(dscaps));
    dscaps.dwSize=sizeof(dscaps);
    rc=IDirectSound_GetCaps(dso,&dscaps);
    ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
    if (rc!=DS_OK)
        goto EXIT;

    /* We must call SetCooperativeLevel before creating primary buffer */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
       DXGetErrorString8(rc));
    if (rc!=DS_OK)
        goto EXIT;

    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DS_OK && primary!=NULL,
       "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
       "%s\n",DXGetErrorString8(rc));

    if (rc==DS_OK && primary!=NULL) {
        rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
        ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
           DXGetErrorString8(rc));
        if (rc!=DS_OK)
            goto EXIT1;

        for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
        for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
            init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
                        fmts[f].channels);
            secondary=NULL;
            ZeroMemory(&bufdesc, sizeof(bufdesc));
            bufdesc.dwSize=sizeof(bufdesc);
            bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
            bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
                                        BUFFER_LEN/1000,wfx.nBlockAlign);
            bufdesc.lpwfxFormat=&wfx;
            if (winetest_interactive) {
                trace("  Testing a secondary buffer at %ldx%dx%d "
                      "with a primary buffer at %ldx%dx%d\n",
                      wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
                      wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
            }
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DS_OK && secondary!=NULL,
               "IDirectSound_CreateSoundBuffer() failed to create a secondary "
               "buffer %s\n",DXGetErrorString8(rc));

            if (rc==DS_OK && secondary!=NULL) {
                test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
                            winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);

                ref=IDirectSoundBuffer_Release(secondary);
                ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
                   "should have 0\n",ref);
            }
        }
        }
EXIT1:
        ref=IDirectSoundBuffer_Release(primary);
        ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
           "should have 0\n",ref);
    }

    /* Set the CooperativeLevel back to normal */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
       DXGetErrorString8(rc));

EXIT:
    ref=IDirectSound_Release(dso);
    ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
    if (ref!=0)
        return DSERR_GENERIC;

    return rc;
}
Пример #5
0
static void IDirectSoundCapture_test(LPDIRECTSOUNDCAPTURE dsco,
                                     BOOL initialized, LPCGUID lpGuid)
{
    HRESULT rc;
    DSCCAPS dsccaps;
    int ref;
    IUnknown * unknown;
    IDirectSoundCapture * dsc;

    /* Try to Query for objects */
    rc=IDirectSoundCapture_QueryInterface(dsco, &IID_IUnknown,
                                          (LPVOID*)&unknown);
    ok(rc==DS_OK, "IDirectSoundCapture_QueryInterface(IID_IUnknown) "
       "failed: %08x\n", rc);
    if (rc==DS_OK)
        IDirectSoundCapture_Release(unknown);

    rc=IDirectSoundCapture_QueryInterface(dsco, &IID_IDirectSoundCapture,
                                          (LPVOID*)&dsc);
    ok(rc==DS_OK, "IDirectSoundCapture_QueryInterface(IID_IDirectSoundCapture) "
       "failed: %08x\n", rc);
    if (rc==DS_OK)
        IDirectSoundCapture_Release(dsc);

    if (initialized == FALSE) {
        /* try uninitialized object */
        rc=IDirectSoundCapture_GetCaps(dsco,0);
        ok(rc==DSERR_UNINITIALIZED||rc==E_INVALIDARG,
           "IDirectSoundCapture_GetCaps(NULL) should have returned "
           "DSERR_UNINITIALIZED or E_INVALIDARG, returned: %08x\n", rc);

        rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSoundCapture_GetCaps() "
           "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);

        rc=IDirectSoundCapture_Initialize(dsco, lpGuid);
        ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||
           rc==E_FAIL||rc==E_INVALIDARG,
           "IDirectSoundCapture_Initialize() failed: %08x\n", rc);
        if (rc==DSERR_NODRIVER||rc==E_INVALIDARG) {
            trace("  No Driver\n");
            goto EXIT;
        } else if (rc==E_FAIL) {
            trace("  No Device\n");
            goto EXIT;
        } else if (rc==DSERR_ALLOCATED) {
            trace("  Already In Use\n");
            goto EXIT;
        }
    }

    rc=IDirectSoundCapture_Initialize(dsco, lpGuid);
    ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSoundCapture_Initialize() "
       "should have returned DSERR_ALREADYINITIALIZED: %08x\n", rc);

    /* DSOUND: Error: Invalid caps buffer */
    rc=IDirectSoundCapture_GetCaps(dsco, 0);
    ok(rc==DSERR_INVALIDPARAM, "IDirectSoundCapture_GetCaps(NULL) "
       "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);

    ZeroMemory(&dsccaps, sizeof(dsccaps));

    /* DSOUND: Error: Invalid caps buffer */
    rc=IDirectSound_GetCaps(dsco, &dsccaps);
    ok(rc==DSERR_INVALIDPARAM, "IDirectSound_GetCaps() "
       "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);

    dsccaps.dwSize=sizeof(dsccaps);

    /* DSOUND: Running on a certified driver */
    rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps);
    ok(rc==DS_OK, "IDirectSoundCapture_GetCaps() failed: %08x\n", rc);

EXIT:
    ref=IDirectSoundCapture_Release(dsco);
    ok(ref==0, "IDirectSoundCapture_Release() has %d references, "
       "should have 0\n", ref);
}
Пример #6
0
/*
	SNDDMA_InitDirect

	Direct-Sound support
*/
sndinitstat
SNDDMA_InitDirect (void)
{
	DSBUFFERDESC dsbuf;
	DSBCAPS     dsbcaps;
	DWORD       dwSize, dwWrite;
	DSCAPS      dscaps;
	WAVEFORMATEX format, pformat;
	HRESULT     hresult;
	int         reps;

	memset ((void *) &sn, 0, sizeof (sn));

	shm = &sn;

	shm->channels = 2;
	shm->samplebits = 16;
	shm->speed = 11025;

	memset (&format, 0, sizeof (format));
	format.wFormatTag = WAVE_FORMAT_PCM;
	format.nChannels = shm->channels;
	format.wBitsPerSample = shm->samplebits;
	format.nSamplesPerSec = shm->speed;
	format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
	format.cbSize = 0;
	format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;

	if (!hInstDS) {
		hInstDS = LoadLibrary ("dsound.dll");

		if (hInstDS == NULL) {
			Con_Printf ("Couldn't load dsound.dll\n");
			return SIS_FAILURE;
		}

		pDirectSoundCreate =
			(void *) GetProcAddress (hInstDS, "DirectSoundCreate");

		if (!pDirectSoundCreate) {
			Con_Printf ("Couldn't get DS proc addr\n");
			return SIS_FAILURE;
		}
	}

	while ((hresult = iDirectSoundCreate (NULL, &pDS, NULL)) != DS_OK) {
		if (hresult != DSERR_ALLOCATED) {
			Con_Printf ("DirectSound create failed\n");
			return SIS_FAILURE;
		}
		Con_Printf ("DirectSoundCreate failure\n"
					"  hardware already in use\n");
		return SIS_NOTAVAIL;
	}

	dscaps.dwSize = sizeof (dscaps);
	if (DS_OK != IDirectSound_GetCaps (pDS, &dscaps)) {
		Con_Printf ("Couldn't get DS caps\n");
	}

	if (dscaps.dwFlags & DSCAPS_EMULDRIVER) {
		Con_Printf ("No DirectSound driver installed\n");
		FreeSound ();
		return SIS_FAILURE;
	}

	if (DS_OK !=
		IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) {
		Con_Printf ("Set coop level failed\n");
		FreeSound ();
		return SIS_FAILURE;
	}
// get access to the primary buffer, if possible, so we can set the
// sound hardware format
	memset (&dsbuf, 0, sizeof (dsbuf));
	dsbuf.dwSize = sizeof (DSBUFFERDESC);
	dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
	dsbuf.dwBufferBytes = 0;
	dsbuf.lpwfxFormat = NULL;

	memset (&dsbcaps, 0, sizeof (dsbcaps));
	dsbcaps.dwSize = sizeof (dsbcaps);
	primary_format_set = false;

	if (!COM_CheckParm ("-snoforceformat")) {
		if (DS_OK ==
			IDirectSound_CreateSoundBuffer (pDS, &dsbuf, &pDSPBuf, NULL)) {
			pformat = format;
	
			if (DS_OK != IDirectSoundBuffer_SetFormat (pDSPBuf, &pformat)) {
			} else primary_format_set = true;
		}
	}

	if (!primary_format_set || !COM_CheckParm ("-primarysound")) {
		// create the secondary buffer we'll actually work with
		memset (&dsbuf, 0, sizeof (dsbuf));
		dsbuf.dwSize = sizeof (DSBUFFERDESC);
		dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
		dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
		dsbuf.lpwfxFormat = &format;

		memset (&dsbcaps, 0, sizeof (dsbcaps));
		dsbcaps.dwSize = sizeof (dsbcaps);

		if (DS_OK !=
			IDirectSound_CreateSoundBuffer (pDS, &dsbuf, &pDSBuf, NULL)) {
			Con_Printf ("DS:CreateSoundBuffer Failed");
			FreeSound ();
			return SIS_FAILURE;
		}

		shm->channels = format.nChannels;
		shm->samplebits = format.wBitsPerSample;
		shm->speed = format.nSamplesPerSec;

		if (DS_OK != IDirectSound_GetCaps (pDSBuf, &dsbcaps)) {
			Con_Printf ("DS:GetCaps failed\n");
			FreeSound ();
			return SIS_FAILURE;
		}
	} else {
		if (DS_OK !=
			IDirectSound_SetCooperativeLevel (pDS, mainwindow,
				  DSSCL_WRITEPRIMARY)) {
			Con_Printf ("Set coop level failed\n");
			FreeSound ();
			return SIS_FAILURE;
		}

		if (DS_OK != IDirectSound_GetCaps (pDSPBuf, &dsbcaps)) {
			Con_Printf ("DS:GetCaps failed\n");
			return SIS_FAILURE;
		}

		pDSBuf = pDSPBuf;
	}

	// Make sure mixer is active
	IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING);

	gSndBufSize = dsbcaps.dwBufferBytes;

// initialize the buffer
	reps = 0;

	while ((hresult = IDirectSoundBuffer_Lock (pDSBuf, 0, gSndBufSize,
			(LPVOID *) & lpData, &dwSize, NULL,NULL, 0)) != DS_OK) {
		if (hresult != DSERR_BUFFERLOST) {
			Con_Printf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
			FreeSound ();
			return SIS_FAILURE;
		}

		if (++reps > 10000) {
			Con_Printf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
			FreeSound ();
			return SIS_FAILURE;
		}

	}

	memset (lpData, 0, dwSize);
//      lpData[4] = lpData[5] = 0x7f;   // force a pop for debugging

	IDirectSoundBuffer_Unlock (pDSBuf, lpData, dwSize, NULL, 0);

	/* we don't want anyone to access the buffer directly w/o locking it
	   first. */
	lpData = NULL;

	IDirectSoundBuffer_Stop (pDSBuf);
	IDirectSoundBuffer_GetCurrentPosition (pDSBuf, &mmstarttime.u.sample,
		&dwWrite);
	IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING);

	shm->soundalive = true;
	shm->splitbuffer = false;
	shm->samples = gSndBufSize / (shm->samplebits / 8);
	shm->samplepos = 0;
	shm->submission_chunk = 1;
	shm->buffer = (unsigned char *) lpData;
	sample16 = (shm->samplebits / 8) - 1;

	dsound_init = true;

	return SIS_SUCCESS;
}
Пример #7
0
static int dsound_init(void)
{
	HRESULT result;

	// now attempt to create it
	result = DirectSoundCreate(NULL, &dsound, NULL);
	if (result != DS_OK)
	{
		fprintf(stderr, "Error creating DirectSound: %08x\n", (UINT32)result);
		goto cant_create_dsound;
	}

	// get the capabilities
	dsound_caps.dwSize = sizeof(dsound_caps);
	result = IDirectSound_GetCaps(dsound, &dsound_caps);
	if (result != DS_OK)
	{
		fprintf(stderr, "Error getting DirectSound capabilities: %08x\n", (UINT32)result);
		goto cant_get_caps;
	}

	// set the cooperative level
	result = IDirectSound_SetCooperativeLevel(dsound, win_window_list->hwnd, DSSCL_PRIORITY);
	if (result != DS_OK)
	{
		fprintf(stderr, "Error setting cooperative level: %08x\n", (UINT32)result);
		goto cant_set_coop_level;
	}

	// make a format description for what we want
	stream_format.wBitsPerSample	= 16;
	stream_format.wFormatTag		= WAVE_FORMAT_PCM;
	stream_format.nChannels			= 2;
	stream_format.nSamplesPerSec	= Machine->sample_rate;
	stream_format.nBlockAlign		= stream_format.wBitsPerSample * stream_format.nChannels / 8;
	stream_format.nAvgBytesPerSec	= stream_format.nSamplesPerSec * stream_format.nBlockAlign;

	// compute the buffer sizes
	stream_buffer_size = ((UINT64)MAX_BUFFER_SIZE * (UINT64)stream_format.nSamplesPerSec) / 44100;
	stream_buffer_size = (stream_buffer_size * stream_format.nBlockAlign) / 4;
	stream_buffer_size = (stream_buffer_size * 30) / Machine->screen[0].refresh;
	stream_buffer_size = (stream_buffer_size / 1024) * 1024;

	// compute the upper/lower thresholds
	lower_thresh = audio_latency * stream_buffer_size / 5;
	upper_thresh = (audio_latency + 1) * stream_buffer_size / 5;
#if LOG_SOUND
	fprintf(sound_log, "stream_buffer_size = %d (max %d)\n", stream_buffer_size, MAX_BUFFER_SIZE);
	fprintf(sound_log, "lower_thresh = %d\n", lower_thresh);
	fprintf(sound_log, "upper_thresh = %d\n", upper_thresh);
#endif

	// create the buffers
	if (dsound_create_buffers())
		goto cant_create_buffers;

	// start playing
	is_enabled = 1;

	result = IDirectSoundBuffer_Play(stream_buffer, 0, 0, DSBPLAY_LOOPING);
	if (result != DS_OK)
	{
		fprintf(stderr, "Error playing: %08x\n", (UINT32)result);
		goto cant_play;
	}
	return 0;

	// error handling
cant_play:
	dsound_destroy_buffers();
cant_create_buffers:
cant_set_coop_level:
cant_get_caps:
	IDirectSound_Release(dsound);
cant_create_dsound:
	dsound = NULL;
	return 0;
}
Пример #8
0
static int dsound_init(void)
{
	HRESULT result;

	LPGUID guid = NULL;	// Default audio device

	osd_enum_audio_devices(); // (Re-)Enumerate devices
	
	// Get the guid to the user selected audio device (NULL if no selected)
	if(current_audio_device>= 0 && current_audio_device<audio_devices_number)
		guid = audio_devices[current_audio_device].guid;

	// now attempt to create it
	result = DirectSoundCreate(guid, &dsound, NULL);
	if (result != DS_OK)
	{
		fprintf(stderr, "Error creating DirectSound: %08x\n", (UINT32)result);
		goto cant_create_dsound;
	}

	// get the capabilities
	dsound_caps.dwSize = sizeof(dsound_caps);
	result = IDirectSound_GetCaps(dsound, &dsound_caps);
	if (result != DS_OK)
	{
		fprintf(stderr, "Error getting DirectSound capabilities: %08x\n", (UINT32)result);
		goto cant_get_caps;
	}

	// set the cooperative level
	result = IDirectSound_SetCooperativeLevel(dsound, win_video_window, DSSCL_PRIORITY);
	if (result != DS_OK)
	{
		fprintf(stderr, "Error setting cooperative level: %08x\n", (UINT32)result);
		goto cant_set_coop_level;
	}

	// make a format description for what we want
	stream_format.wBitsPerSample	= 16;
	stream_format.wFormatTag		= WAVE_FORMAT_PCM;
	stream_format.nChannels			= (Machine->drv->sound_attributes & SOUND_SUPPORTS_STEREO) ? 2 : 1;
	stream_format.nSamplesPerSec	= Machine->sample_rate;
	stream_format.nBlockAlign		= stream_format.wBitsPerSample * stream_format.nChannels / 8;
	stream_format.nAvgBytesPerSec	= stream_format.nSamplesPerSec * stream_format.nBlockAlign;

	// compute the buffer sizes
	stream_buffer_size = ((UINT64)MAX_BUFFER_SIZE * (UINT64)stream_format.nSamplesPerSec) / 44100;
	stream_buffer_size = (stream_buffer_size * stream_format.nBlockAlign) / 4;
	stream_buffer_size = (stream_buffer_size * 30) / Machine->drv->frames_per_second;
	stream_buffer_size = (stream_buffer_size / 1024) * 1024;

	// compute the upper/lower thresholds
	lower_thresh = audio_latency * stream_buffer_size / 5;
	upper_thresh = (audio_latency + 1) * stream_buffer_size / 5;
#if LOG_SOUND
	fprintf(sound_log, "stream_buffer_size = %d (max %d)\n", stream_buffer_size, MAX_BUFFER_SIZE);
	fprintf(sound_log, "lower_thresh = %d\n", lower_thresh);
	fprintf(sound_log, "upper_thresh = %d\n", upper_thresh);
#endif

	// create the buffers
	if (dsound_create_buffers())
		goto cant_create_buffers;

	// start playing
	is_enabled = 1;

	result = IDirectSoundBuffer_Play(stream_buffer, 0, 0, DSBPLAY_LOOPING);
	if (result != DS_OK)
	{
		fprintf(stderr, "Error playing: %08x\n", (UINT32)result);
		goto cant_play;
	}
	return 0;

	// error handling
cant_play:
	dsound_destroy_buffers();
cant_create_buffers:
cant_set_coop_level:
cant_get_caps:
	IDirectSound_Release(dsound);
cant_create_dsound:
	dsound = NULL;
	return 0;
}
Пример #9
0
static HRESULT test_primary(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND dso=NULL;
    LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
    DSBUFFERDESC bufdesc;
    DSCAPS dscaps;
    WAVEFORMATEX wfx;
    int ref;

    /* Create the DirectSound object */
    rc=DirectSoundCreate(lpGuid,&dso,NULL);
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
       "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
    if (rc!=DS_OK)
        return rc;

    /* Get the device capabilities */
    ZeroMemory(&dscaps, sizeof(dscaps));
    dscaps.dwSize=sizeof(dscaps);
    rc=IDirectSound_GetCaps(dso,&dscaps);
    ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
    if (rc!=DS_OK)
        goto EXIT;

    /* DSOUND: Error: Invalid buffer description pointer */
    rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
    ok(rc==DSERR_INVALIDPARAM,
       "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
       DXGetErrorString8(rc));

    /* DSOUND: Error: Invalid buffer description pointer */
    rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
    ok(rc==DSERR_INVALIDPARAM && primary==0,
       "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
       "dsbo=%p\n",DXGetErrorString8(rc),primary);

    /* DSOUND: Error: Invalid buffer description pointer */
    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
    ok(rc==DSERR_INVALIDPARAM && primary==0,
       "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
       "dsbo=0x%p\n",DXGetErrorString8(rc),primary);

    ZeroMemory(&bufdesc, sizeof(bufdesc));

    /* DSOUND: Error: Invalid size */
    /* DSOUND: Error: Invalid buffer description */
    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DSERR_INVALIDPARAM && primary==0,
       "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
       "primary=%p\n",DXGetErrorString8(rc),primary);

    /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
       DXGetErrorString8(rc));
    if (rc!=DS_OK)
        goto EXIT;

    /* Testing the primary buffer */
    primary=NULL;
    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
    bufdesc.lpwfxFormat = &wfx;
    init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
       "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
    if (rc==DS_OK && primary!=NULL)
        IDirectSoundBuffer_Release(primary);

    primary=NULL;
    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
       "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
       "%s\n",DXGetErrorString8(rc));
    if (rc==DSERR_CONTROLUNAVAIL)
        trace("  No Primary\n");
    else if (rc==DS_OK && primary!=NULL) {
        LONG vol;

        /* Try to create a second primary buffer */
        /* DSOUND: Error: The primary buffer already exists.
         * Any changes made to the buffer description will be ignored. */
        rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
        ok(rc==DS_OK && second==primary,
           "IDirectSound_CreateSoundBuffer() should have returned original "
           "primary buffer: %s\n",DXGetErrorString8(rc));
        ref=IDirectSoundBuffer_Release(second);
        ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
           "should have 1\n",ref);

        /* Try to duplicate a primary buffer */
        /* DSOUND: Error: Can't duplicate primary buffers */
        rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
        /* rc=0x88780032 */
        ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
           "should have failed %s\n",DXGetErrorString8(rc));

        rc=IDirectSoundBuffer_GetVolume(primary,&vol);
        ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
           DXGetErrorString8(rc));

        if (winetest_interactive) {
            trace("Playing a 5 seconds reference tone at the current "
                  "volume.\n");
            if (rc==DS_OK)
                trace("(the current volume is %ld according to DirectSound)\n",
                      vol);
            trace("All subsequent tones should be identical to this one.\n");
            trace("Listen for stutter, changes in pitch, volume, etc.\n");
        }
        test_buffer(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive &&
                    !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);

        ref=IDirectSoundBuffer_Release(primary);
        ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
           "should have 0\n",ref);
    }

    /* Set the CooperativeLevel back to normal */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
       DXGetErrorString8(rc));

EXIT:
    ref=IDirectSound_Release(dso);
    ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
    if (ref!=0)
        return DSERR_GENERIC;

    return rc;
}
Пример #10
0
static HRESULT dsound_init(running_machine *machine)
{
	HRESULT result;

	// create the DirectSound object
	result = DirectSoundCreate(NULL, &dsound, NULL);
	if (result != DS_OK)
	{
		mame_printf_error("Error creating DirectSound: %08x\n", (UINT32)result);
		goto error;
	}

	// get the capabilities
	dsound_caps.dwSize = sizeof(dsound_caps);
	result = IDirectSound_GetCaps(dsound, &dsound_caps);
	if (result != DS_OK)
	{
		mame_printf_error("Error getting DirectSound capabilities: %08x\n", (UINT32)result);
		goto error;
	}

	// set the cooperative level
	result = IDirectSound_SetCooperativeLevel(dsound, win_window_list->hwnd, DSSCL_PRIORITY);
	if (result != DS_OK)
	{
		mame_printf_error("Error setting DirectSound cooperative level: %08x\n", (UINT32)result);
		goto error;
	}

	// make a format description for what we want
	stream_format.wBitsPerSample	= 16;
	stream_format.wFormatTag		= WAVE_FORMAT_PCM;
	stream_format.nChannels			= 2;
	stream_format.nSamplesPerSec	= machine->sample_rate;
	stream_format.nBlockAlign		= stream_format.wBitsPerSample * stream_format.nChannels / 8;
	stream_format.nAvgBytesPerSec	= stream_format.nSamplesPerSec * stream_format.nBlockAlign;

	// compute the buffer size based on the output sample rate
	stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * options_get_int(machine->options(), WINOPTION_AUDIO_LATENCY) / 10;
	stream_buffer_size = (stream_buffer_size / 1024) * 1024;
	if (stream_buffer_size < 1024)
		stream_buffer_size = 1024;

	LOG(("stream_buffer_size = %d\n", stream_buffer_size));

	// create the buffers
	result = dsound_create_buffers();
	if (result != DS_OK)
		goto error;

	// start playing
	result = IDirectSoundBuffer_Play(stream_buffer, 0, 0, DSBPLAY_LOOPING);
	if (result != DS_OK)
	{
		mame_printf_error("Error playing: %08x\n", (UINT32)result);
		goto error;
	}
	return DS_OK;

	// error handling
error:
	dsound_destroy_buffers();
	dsound_kill();
	return result;
}
Пример #11
0
static HRESULT test_secondary(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND dso=NULL;
    LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
    DSBUFFERDESC bufdesc;
    DSCAPS dscaps;
    WAVEFORMATEX wfx, wfx1;
    DWORD f;
    int ref;

    /* Create the DirectSound object */
    rc=pDirectSoundCreate(lpGuid,&dso,NULL);
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
       "DirectSoundCreate() failed: %08x\n",rc);
    if (rc!=DS_OK)
        return rc;

    /* Get the device capabilities */
    ZeroMemory(&dscaps, sizeof(dscaps));
    dscaps.dwSize=sizeof(dscaps);
    rc=IDirectSound_GetCaps(dso,&dscaps);
    ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %08x\n",rc);
    if (rc!=DS_OK)
        goto EXIT;

    /* We must call SetCooperativeLevel before creating primary buffer */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);
    if (rc!=DS_OK)
        goto EXIT;

    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DS_OK && primary!=NULL,
       "IDirectSound_CreateSoundBuffer() failed to create a primary buffer %08x\n",rc);

    if (rc==DS_OK && primary!=NULL) {
        rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
        ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
        if (rc!=DS_OK)
            goto EXIT1;

        for (f=0;f<NB_FORMATS;f++) {
            WAVEFORMATEXTENSIBLE wfxe;
            init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
                        formats[f][2]);
            secondary=NULL;
            ZeroMemory(&bufdesc, sizeof(bufdesc));
            bufdesc.dwSize=sizeof(bufdesc);
            bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
            bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
                                        wfx.nBlockAlign);
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
               "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
            if (rc==DS_OK && secondary!=NULL)
                IDirectSoundBuffer_Release(secondary);

            secondary=NULL;
            ZeroMemory(&bufdesc, sizeof(bufdesc));
            bufdesc.dwSize=sizeof(bufdesc);
            bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
            bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
                                        wfx.nBlockAlign);
            bufdesc.lpwfxFormat=&wfx;
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            if (gotdx8 || wfx.wBitsPerSample <= 16)
            {
                if (wfx.wBitsPerSample > 16)
                    ok(((rc == DSERR_CONTROLUNAVAIL || rc == DSERR_INVALIDCALL || rc == DSERR_INVALIDPARAM /* 2003 */) && !secondary)
                        || rc == DS_OK, /* driver dependent? */
                        "IDirectSound_CreateSoundBuffer() "
                        "should have returned (DSERR_CONTROLUNAVAIL or DSERR_INVALIDCALL) "
                        "and NULL, returned: %08x %p\n", rc, secondary);
                else
                    ok(rc==DS_OK && secondary!=NULL,
                        "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);
            }
            else
                ok(rc==E_INVALIDARG, "Creating %d bpp buffer on dx < 8 returned: %p %08x\n",
                   wfx.wBitsPerSample, secondary, rc);

            if (!gotdx8)
            {
                skip("Not doing the WAVE_FORMAT_EXTENSIBLE tests\n");
                /* Apparently they succeed with bogus values,
                 * which means that older dsound doesn't look at them
                 */
                goto no_wfe;
            }

            if (secondary)
                IDirectSoundBuffer_Release(secondary);
            secondary = NULL;

            bufdesc.lpwfxFormat=(WAVEFORMATEX*)&wfxe;
            wfxe.Format = wfx;
            wfxe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
            wfxe.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
            wfxe.Format.cbSize = 1;
            wfxe.Samples.wValidBitsPerSample = wfx.wBitsPerSample;
            wfxe.dwChannelMask = (wfx.nChannels == 1 ? KSAUDIO_SPEAKER_MONO : KSAUDIO_SPEAKER_STEREO);

            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL /* 2003 */) && !secondary,
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
            if (secondary)
            {
                IDirectSoundBuffer_Release(secondary);
                secondary=NULL;
            }

            wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx) + 1;

            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL || rc==DSERR_INVALIDPARAM)
                && !secondary)
               || rc==DS_OK, /* 2003 / 2008 */
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
            if (secondary)
            {
                IDirectSoundBuffer_Release(secondary);
                secondary=NULL;
            }

            wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx);
            wfxe.SubFormat = GUID_NULL;
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL) && !secondary,
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
            if (secondary)
            {
                IDirectSoundBuffer_Release(secondary);
                secondary=NULL;
            }
            wfxe.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;

            ++wfxe.Samples.wValidBitsPerSample;
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DSERR_INVALIDPARAM && !secondary,
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
            if (secondary)
            {
                IDirectSoundBuffer_Release(secondary);
                secondary=NULL;
            }
            --wfxe.Samples.wValidBitsPerSample;

            wfxe.Samples.wValidBitsPerSample = 0;
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DS_OK && secondary,
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
            if (secondary)
            {
                IDirectSoundBuffer_Release(secondary);
                secondary=NULL;
            }
            wfxe.Samples.wValidBitsPerSample = wfxe.Format.wBitsPerSample;

            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DS_OK && secondary!=NULL,
                "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer %08x\n",rc);

no_wfe:
            if (rc==DS_OK && secondary!=NULL) {
                if (winetest_interactive) {
                    trace("  Testing a secondary buffer at %dx%dx%d "
                        "with a primary buffer at %dx%dx%d\n",
                        wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
                        wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
                }
                test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
                            winetest_interactive,1.0,0,NULL,0,0,FALSE,0);

                ref=IDirectSoundBuffer_Release(secondary);
                ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
                   "should have 0\n",ref);
            }
        }
EXIT1:
        ref=IDirectSoundBuffer_Release(primary);
        ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
           "should have 0\n",ref);
    }

    /* Set the CooperativeLevel back to normal */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc);

EXIT:
    ref=IDirectSound_Release(dso);
    ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
    if (ref!=0)
        return DSERR_GENERIC;

    return rc;
}
Пример #12
0
HRESULT sound_direct_sound::dsound_init()
{
	HRESULT result;

	// create the DirectSound object
	result = DirectSoundCreate(NULL, &dsound, NULL);
	if (result != DS_OK)
	{
		osd_printf_error("Error creating DirectSound: %08x\n", (UINT32)result);
		goto error;
	}

	// get the capabilities
	dsound_caps.dwSize = sizeof(dsound_caps);
	result = IDirectSound_GetCaps(dsound, &dsound_caps);
	if (result != DS_OK)
	{
		osd_printf_error("Error getting DirectSound capabilities: %08x\n", (UINT32)result);
		goto error;
	}

	// set the cooperative level
	#ifdef SDLMAME_WIN32
	SDL_SysWMinfo wminfo;
	SDL_VERSION(&wminfo.version);
#if (SDLMAME_SDL2)
	SDL_GetWindowWMInfo(sdl_window_list->sdl_window(), &wminfo);
	result = IDirectSound_SetCooperativeLevel(dsound, wminfo.info.win.window, DSSCL_PRIORITY);
#else
	SDL_GetWMInfo(&wminfo);
	result = IDirectSound_SetCooperativeLevel(dsound, wminfo.window, DSSCL_PRIORITY);
#endif
	#else
	result = IDirectSound_SetCooperativeLevel(dsound, win_window_list->m_hwnd, DSSCL_PRIORITY);
	#endif
	if (result != DS_OK)
	{
		osd_printf_error("Error setting DirectSound cooperative level: %08x\n", (UINT32)result);
		goto error;
	}

	// make a format description for what we want
	stream_format.wBitsPerSample    = 16;
	stream_format.wFormatTag        = WAVE_FORMAT_PCM;
	stream_format.nChannels         = 2;
	stream_format.nSamplesPerSec    = sample_rate();
	stream_format.nBlockAlign       = stream_format.wBitsPerSample * stream_format.nChannels / 8;
	stream_format.nAvgBytesPerSec   = stream_format.nSamplesPerSec * stream_format.nBlockAlign;


	// compute the buffer size based on the output sample rate
	int audio_latency;
	audio_latency = m_audio_latency;

	stream_buffer_size = stream_format.nSamplesPerSec * stream_format.nBlockAlign * audio_latency / 10;
	stream_buffer_size = (stream_buffer_size / 1024) * 1024;
	if (stream_buffer_size < 1024)
		stream_buffer_size = 1024;

	LOG(("stream_buffer_size = %d\n", stream_buffer_size));

	// create the buffers
	result = dsound_create_buffers();
	if (result != DS_OK)
		goto error;

	// start playing
	result = IDirectSoundBuffer_Play(stream_buffer, 0, 0, DSBPLAY_LOOPING);
	if (result != DS_OK)
	{
		osd_printf_error("Error playing: %08x\n", (UINT32)result);
		goto error;
	}
	return DS_OK;

	// error handling
error:
	dsound_destroy_buffers();
	dsound_kill();
	return result;
}
Пример #13
0
/*
==================
SndSys_InitDirectSound

DirectSound 5 support
==================
*/
static sndinitstat SndSys_InitDirectSound (const snd_format_t* requested)
{
	DSBUFFERDESC			dsbuf;
	DSBCAPS					dsbcaps;
	DWORD					dwSize;
	DSCAPS					dscaps;
	WAVEFORMATEXTENSIBLE	format, pformat;
	HRESULT					hresult;
	int						reps;

	if (! SndSys_BuildWaveFormat(requested, &format))
		return SIS_FAILURE;

	if (!hInstDS)
	{
		hInstDS = LoadLibrary("dsound.dll");

		if (hInstDS == NULL)
		{
			Con_Print("Couldn't load dsound.dll\n");
			return SIS_FAILURE;
		}

		pDirectSoundCreate = (HRESULT (__stdcall *)(GUID *, LPDIRECTSOUND *,IUnknown *))GetProcAddress(hInstDS,"DirectSoundCreate");

		if (!pDirectSoundCreate)
		{
			Con_Print("Couldn't get DS proc addr\n");
			return SIS_FAILURE;
		}
	}

	while ((hresult = pDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK)
	{
		if (hresult != DSERR_ALLOCATED)
		{
			Con_Print("DirectSound create failed\n");
			return SIS_FAILURE;
		}

		if (MessageBox (NULL,
						"The sound hardware is in use by another app.\n\n"
					    "Select Retry to try to start sound again or Cancel to run Quake with no sound.",
						"Sound not available",
						MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
		{
			Con_Print("DirectSoundCreate failure\n  hardware already in use\n");
			return SIS_NOTAVAIL;
		}
	}

	dscaps.dwSize = sizeof(dscaps);

	if (DS_OK != IDirectSound_GetCaps (pDS, &dscaps))
	{
		Con_Print("Couldn't get DS caps\n");
	}

	if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
	{
		Con_Print("No DirectSound driver installed\n");
		SndSys_Shutdown ();
		return SIS_FAILURE;
	}

	if (DS_OK != IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE))
	{
		Con_Print("Set coop level failed\n");
		SndSys_Shutdown ();
		return SIS_FAILURE;
	}

	// get access to the primary buffer, if possible, so we can set the
	// sound hardware format
	memset (&dsbuf, 0, sizeof(dsbuf));
	dsbuf.dwSize = sizeof(DSBUFFERDESC);
	dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
	dsbuf.dwBufferBytes = 0;
	dsbuf.lpwfxFormat = NULL;

	memset(&dsbcaps, 0, sizeof(dsbcaps));
	dsbcaps.dwSize = sizeof(dsbcaps);
	primary_format_set = false;

// COMMANDLINEOPTION: Windows DirectSound: -snoforceformat uses the format that DirectSound returns, rather than forcing it
	if (!COM_CheckParm ("-snoforceformat"))
	{
		if (DS_OK == IDirectSound_CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL))
		{
			pformat = format;

			if (DS_OK != IDirectSoundBuffer_SetFormat (pDSPBuf, (WAVEFORMATEX*)&pformat))
			{
				Con_Print("Set primary sound buffer format: no\n");
			}
			else
			{
				Con_Print("Set primary sound buffer format: yes\n");

				primary_format_set = true;
			}
		}
	}

// COMMANDLINEOPTION: Windows DirectSound: -primarysound locks the sound hardware for exclusive use
	if (!primary_format_set || !COM_CheckParm ("-primarysound"))
	{
		HRESULT result;

		// create the secondary buffer we'll actually work with
		memset (&dsbuf, 0, sizeof(dsbuf));
		dsbuf.dwSize = sizeof(DSBUFFERDESC);
		dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
		dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE(requested);
		dsbuf.lpwfxFormat = (WAVEFORMATEX*)&format;

		memset(&dsbcaps, 0, sizeof(dsbcaps));
		dsbcaps.dwSize = sizeof(dsbcaps);

		result = IDirectSound_CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL);
		if (result != DS_OK ||
			requested->channels != format.Format.nChannels ||
			requested->width != format.Format.wBitsPerSample / 8 ||
			requested->speed != format.Format.nSamplesPerSec)
		{
			Con_Printf("DS:CreateSoundBuffer Failed (%d): channels=%u, width=%u, speed=%u\n",
					   (int)result, (unsigned)format.Format.nChannels, (unsigned)format.Format.wBitsPerSample / 8, (unsigned)format.Format.nSamplesPerSec);
			SndSys_Shutdown ();
			return SIS_FAILURE;
		}

		if (DS_OK != IDirectSoundBuffer_GetCaps (pDSBuf, &dsbcaps))
		{
			Con_Print("DS:GetCaps failed\n");
			SndSys_Shutdown ();
			return SIS_FAILURE;
		}

		Con_Print("Using secondary sound buffer\n");
	}
	else
	{
		if (DS_OK != IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY))
		{
			Con_Print("Set coop level failed\n");
			SndSys_Shutdown ();
			return SIS_FAILURE;
		}

		if (DS_OK != IDirectSoundBuffer_GetCaps (pDSPBuf, &dsbcaps))
		{
			Con_Print("DS:GetCaps failed\n");
			return SIS_FAILURE;
		}

		pDSBuf = pDSPBuf;
		Con_Print("Using primary sound buffer\n");
	}

	// Make sure mixer is active
	IDirectSoundBuffer_Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);

	Con_Printf("   %d channel(s)\n"
				"   %d bits/sample\n"
				"   %d samples/sec\n",
				requested->channels, requested->width * 8, requested->speed);

	gSndBufSize = dsbcaps.dwBufferBytes;

	// initialize the buffer
	reps = 0;

	while ((hresult = IDirectSoundBuffer_Lock(pDSBuf, 0, gSndBufSize, (LPVOID*)&lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
	{
		if (hresult != DSERR_BUFFERLOST)
		{
			Con_Print("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
			SndSys_Shutdown ();
			return SIS_FAILURE;
		}

		if (++reps > 10000)
		{
			Con_Print("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
			SndSys_Shutdown ();
			return SIS_FAILURE;
		}

	}

	memset(lpData, 0, dwSize);
	IDirectSoundBuffer_Unlock(pDSBuf, lpData, dwSize, NULL, 0);

	IDirectSoundBuffer_Stop(pDSBuf);
	IDirectSoundBuffer_Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);

	dwStartTime = 0;
	dsound_time = 0;
	snd_renderbuffer = Snd_CreateRingBuffer(requested, gSndBufSize / (requested->width * requested->channels), lpData);

	dsound_init = true;

	return SIS_SUCCESS;
}
Пример #14
0
void * DSGetMultiWave( WAVEFORMATEX *pWaveHeaderStore, BYTE **ppbWaveData, DWORD *pcbWaveSize, DWORD dwFlags, int *num_allocated_ptr )
{
    long File_Size;
    long Read_Size;
    void *Buffer;
    void *End;
    int i, min, index, variant;
    char *TempCompositeBuffer, *CompositeBuffer, *IntermediateBuffer;
    char TempFileName[256];
    WAVEFORMATEX TempWaveHeader;
    int temp_num_allocated;

    LPWAVEFORMATEX pWaveHeader;
    
    DWORD BytesPerSec, dwGapSize, total_size, dwBufferOffset;
    float gap_size; 
    
    DWORD BufferSizeSoFar, MaxBufferSize;
    BOOL SfxChecked[ MAX_SFX ];
    DSCAPS DSCaps;
    BOOL error;
    
    memset (&DSCaps, 0, sizeof (DSCAPS));
    DSCaps.dwSize = sizeof(DSCAPS);
    IDirectSound_GetCaps( lpDS, &DSCaps );
    
    memset (SfxChecked, 0, sizeof( BOOL ) * MAX_SFX);

    BytesPerSec = (CompoundSfxBitDepth * CompoundSfxChannels / 8) * CompoundSfxFrequency;
    gap_size = (float)BytesPerSec * CompoundSfxGap;
    dwGapSize = (DWORD)gap_size;

    total_size = 0;

    // for all compound sfx...
    for ( i = 0; Sfx_Filenames[ i ].Name; i++ )
    {
        if ( ( IS_COMPOUND( Sfx_Filenames[ i ].Flags ) ) && !CompoundSfxAllocated[ i ] && SndLookup[ i ].Requested )
        {
            // if sfx does not exist, ignore
            if ( !SndLookup[ i ].Num_Variants )
                continue;

            for ( variant = 0; variant < SndLookup[ i ].Num_Variants; variant++ )
            {
                GetFullSfxPath( TempFileName, i, variant, SndLookup[ i ].Num_Variants );

                if ( File_Exists( TempFileName ) )
                {
                    File_Size = Get_File_Size( TempFileName );  // how big is the file...
                    if( !File_Size ) return NULL;

                    Buffer = malloc( File_Size );                           // alloc enough space to load it...
                    if( Buffer == NULL ) return( NULL );                    // if couldnt then return

                    Read_Size = Read_File( TempFileName, Buffer, File_Size ); // Read it in making a note of the Size returned
                    if( Read_Size != File_Size ) return( NULL );            // if size read doesnt qual file size return

                    DSParseWave( Buffer, &pWaveHeader, ppbWaveData, pcbWaveSize, &End);

                    // get size of file...
                    total_size += *pcbWaveSize;
                        
                    // add space for gap afterwards...
                    total_size += dwGapSize;

                    free ( Buffer );
                }
            }
        }
    }

    if ( dwFlags & DSBCAPS_LOCHARDWARE )
        MaxBufferSize = DSCaps.dwMaxContigFreeHwMemBytes;
    else
    {
        return NULL;
    }

    if ( total_size > MaxBufferSize )
        total_size = MaxBufferSize;

    if ( CustomCompoundBufferSize && ( total_size > UserTotalCompoundSfxBufferSize ) )
        total_size = UserTotalCompoundSfxBufferSize;

    CompositeBuffer = (char *)malloc( total_size );
    TempCompositeBuffer = CompositeBuffer;
    dwBufferOffset = 0;
    BufferSizeSoFar = 0;
    do
    {
        min = -1;
        index = -1;

        // find sfx with next highest priority...
        for ( i = 0; Sfx_Filenames[ i ].Name; i++ )
        {
            if ( IS_COMPOUND( Sfx_Filenames[ i ].Flags ) )
            {
                if ( ( min == -1 ) && !SfxChecked[ i ] && !CompoundSfxAllocated[ i ] && SndLookup[ i ].Num_Variants && SndLookup[ i ].Requested )
                {
                    min = Sfx_Filenames[ i ].Priority;
                    index = i;
                }else
                {
                    if ( ( Sfx_Filenames[ i ].Priority < min ) && !SfxChecked[ i ] && !CompoundSfxAllocated[ i ] && SndLookup[ i ].Num_Variants && SndLookup[ i ].Requested )
                    {
                        min = Sfx_Filenames[ i ].Priority;
                        index = i;
                    }
                }
            }
        }

        if ( index != -1 )  // sfx has been found...
        {
            SfxChecked[ index ] = TRUE;

            error = FALSE;
            IntermediateBuffer = TempCompositeBuffer;
            temp_num_allocated = *num_allocated_ptr;

            for ( variant = 0; variant < SndLookup[ index ].Num_Variants; variant++ )
            {

                GetFullSfxPath( TempFileName, index, variant, SndLookup[ index ].Num_Variants );
            
                if ( File_Exists( TempFileName ) )
                {
                    File_Size = Get_File_Size( TempFileName );  // how big is the file...
                    if( !File_Size )
                    {
                        error = TRUE;
                        DebugPrintf("DSGetMultiWave() File size returned was zero\n");
                        break;
                    }

                    Buffer = malloc( File_Size );        // alloc enough space to load it...

                    if( Buffer == NULL )
                    {
                        error = TRUE;
                        DebugPrintf("DSGetMultiWave() unable to malloc memory for temp buffer\n");
                        break;
                    }

                    Read_Size = Read_File( TempFileName, Buffer, File_Size ); // Read it in making a note of the Size returned

                    if( Read_Size != File_Size )
                    {
                        error = TRUE;
                        DebugPrintf("DSGetMultiWave() read file size not equal to actual file size\n");
                        break;
                    }

                    DSParseWave( Buffer, &pWaveHeader, ppbWaveData, pcbWaveSize, &End);

                    if ( ( (pWaveHeader)->nChannels != CompoundSfxChannels ) ||
                        ( (pWaveHeader)->nSamplesPerSec != CompoundSfxFrequency ) ||
                        ( (pWaveHeader)->wBitsPerSample != CompoundSfxBitDepth ) )
                    {
                        DebugPrintf("Dsutil.c: DSGetMultiWave() - sfx %d variant %d not of correct type for composite buffer, ignoring\n", index, variant);
                        *pWaveHeader = TempWaveHeader;
                        error = TRUE;
                        break;
                    }else
                    {
                        TempWaveHeader = *pWaveHeader;

                        // if pcbWaveSize < available mem left, and format is OK...
                        if ( ( (*pcbWaveSize + dwGapSize) < ( total_size - BufferSizeSoFar ) ) || !total_size )
                        {
                            //DebugPrintf("sfx %d marked allocated\n", index);
                           
                            BufferSizeSoFar += *pcbWaveSize + dwGapSize;

                            TempSfxInfo[ *num_allocated_ptr ].SfxNum = index;
                            TempSfxInfo[ *num_allocated_ptr ].StartPos = dwBufferOffset;
                            TempSfxInfo[ *num_allocated_ptr ].Length = (*pcbWaveSize * 1000) / BytesPerSec;
                            TempSfxInfo[ *num_allocated_ptr ].Bytes = *pcbWaveSize;
                            TempSfxInfo[ *num_allocated_ptr ].Variant = variant;

                            (*num_allocated_ptr)++;

                            // check to see if max sfx allocated...
                            if (*num_allocated_ptr == MAX_COMPOUND_SFX)
                            {
                                DebugPrintf("tried to allocate more than MAX_COMPOUND_SFX sfx\n");
                                error = TRUE;
                                break;
                            }

                            dwBufferOffset = dwBufferOffset + *pcbWaveSize + dwGapSize;

                            // copy wave data to composite buffer...
                            memcpy( TempCompositeBuffer, *ppbWaveData, *pcbWaveSize );
                            TempCompositeBuffer += *pcbWaveSize;
                            
                            // add gap
                            memset( TempCompositeBuffer, 0, dwGapSize );
                            TempCompositeBuffer += dwGapSize;
                        }else
                        {
                            DebugPrintf("Not enough HW mem for SFX %d\n", index);
                            error = TRUE;
                            break;
                        }
                    }

                    *pWaveHeaderStore = *pWaveHeader;

                    free ( Buffer );
                }
            }

            if ( error )
            {
                if ( Buffer )
                    free ( Buffer );
                
                // move current buffer ptr back to position b4 this sfx
                TempCompositeBuffer = IntermediateBuffer;

                // invalidate compound sfx info for this sfx
                *num_allocated_ptr = temp_num_allocated;
            }else
            {
                CompoundSfxAllocated[ index ] = TRUE;
            }
        }
    }while ( index != -1 );

    *pcbWaveSize = BufferSizeSoFar;

    return (void *)CompositeBuffer;
}
Пример #15
0
/**
\brief initilize direct sound
\return 0 if error, 1 if ok
*/
static int InitDirectSound(struct ao *ao)
{
    struct priv *p = ao->priv;

    DSCAPS dscaps;

    // initialize directsound
    HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
    HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKA, LPVOID);
    p->device_index = 0;
    p->device_num = p->cfg_device;

    p->hdsound_dll = LoadLibrary("DSOUND.DLL");
    if (p->hdsound_dll == NULL) {
        MP_ERR(ao, "cannot load DSOUND.DLL\n");
        return 0;
    }
    OurDirectSoundCreate = (void *)GetProcAddress(p->hdsound_dll,
                                                  "DirectSoundCreate");
    OurDirectSoundEnumerate = (void *)GetProcAddress(p->hdsound_dll,
                                                     "DirectSoundEnumerateA");

    if (OurDirectSoundCreate == NULL || OurDirectSoundEnumerate == NULL) {
        MP_ERR(ao, "GetProcAddress FAILED\n");
        FreeLibrary(p->hdsound_dll);
        return 0;
    }

    // Enumerate all directsound p->devices
    MP_VERBOSE(ao, "Output Devices:\n");
    OurDirectSoundEnumerate(DirectSoundEnum, ao);

    // Create the direct sound object
    if (FAILED(OurDirectSoundCreate((p->device_num) ? &p->device : NULL,
                                    &p->hds, NULL)))
    {
        MP_ERR(ao, "cannot create a DirectSound device\n");
        FreeLibrary(p->hdsound_dll);
        return 0;
    }

    /* Set DirectSound Cooperative level, ie what control we want over Windows
     * sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
     * settings of the primary buffer, but also that only the sound of our
     * application will be hearable when it will have the focus.
     * !!! (this is not really working as intended yet because to set the
     * cooperative level you need the window handle of your application, and
     * I don't know of any easy way to get it. Especially since we might play
     * sound without any video, and so what window handle should we use ???
     * The hack for now is to use the Desktop window handle - it seems to be
     * working */
    if (IDirectSound_SetCooperativeLevel(p->hds, GetDesktopWindow(),
                                         DSSCL_EXCLUSIVE))
    {
        MP_ERR(ao, "cannot set direct sound cooperative level\n");
        IDirectSound_Release(p->hds);
        FreeLibrary(p->hdsound_dll);
        return 0;
    }
    MP_VERBOSE(ao, "DirectSound initialized\n");

    memset(&dscaps, 0, sizeof(DSCAPS));
    dscaps.dwSize = sizeof(DSCAPS);
    if (DS_OK == IDirectSound_GetCaps(p->hds, &dscaps)) {
        if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
            MP_VERBOSE(ao, "DirectSound is emulated\n");
    } else {
        MP_VERBOSE(ao, "cannot get device capabilities\n");
    }

    return 1;
}
Пример #16
0
static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
                              LPCGUID lpGuid)
{
    HRESULT rc;
    DSCAPS dscaps;
    int ref;
    IUnknown * unknown;
    IDirectSound * ds;
    IDirectSound8 * ds8;
    DWORD speaker_config, new_speaker_config;

    /* Try to Query for objects */
    rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
    ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
       DXGetErrorString8(rc));
    if (rc==DS_OK)
        IDirectSound_Release(unknown);

    rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
    ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",
       DXGetErrorString8(rc));
    if (rc==DS_OK)
        IDirectSound_Release(ds);

    rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
    ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
       "should have failed: %s\n",DXGetErrorString8(rc));
    if (rc==DS_OK)
        IDirectSound8_Release(ds8);

    if (initialized == FALSE) {
        /* try unitialized object */
        rc=IDirectSound_GetCaps(dso,0);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
           "should have returned DSERR_UNINITIALIZED, returned: %s\n",
           DXGetErrorString8(rc));

        rc=IDirectSound_GetCaps(dso,&dscaps);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
           "should have returned DSERR_UNINITIALIZED, returned: %s\n",
           DXGetErrorString8(rc));

        rc=IDirectSound_Compact(dso);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
           "should have returned DSERR_UNINITIALIZED, returned: %s\n",
           DXGetErrorString8(rc));

        rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
           "should have returned DSERR_UNINITIALIZED, returned: %s\n",
           DXGetErrorString8(rc));

        rc=IDirectSound_Initialize(dso,lpGuid);
        ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
           "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc));
        if (rc==DSERR_NODRIVER) {
            trace("  No Driver\n");
            goto EXIT;
        } else if (rc==E_FAIL) {
            trace("  No Device\n");
            goto EXIT;
        } else if (rc==DSERR_ALLOCATED) {
            trace("  Already In Use\n");
            goto EXIT;
        }
    }

    rc=IDirectSound_Initialize(dso,lpGuid);
    ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound_Initialize() "
       "should have returned DSERR_ALREADYINITIALIZED: %s\n",
       DXGetErrorString8(rc));

    /* DSOUND: Error: Invalid caps buffer */
    rc=IDirectSound_GetCaps(dso,0);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
       "should have returned DSERR_INVALIDPARAM, returned: %s\n",
       DXGetErrorString8(rc));

    ZeroMemory(&dscaps, sizeof(dscaps));

    /* DSOUND: Error: Invalid caps buffer */
    rc=IDirectSound_GetCaps(dso,&dscaps);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
       "should have returned DSERR_INVALIDPARAM, returned: %s\n",
       DXGetErrorString8(rc));

    dscaps.dwSize=sizeof(dscaps);

    /* DSOUND: Running on a certified driver */
    rc=IDirectSound_GetCaps(dso,&dscaps);
    ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));

    rc=IDirectSound_Compact(dso);
    ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
       DXGetErrorString8(rc));

    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
       DXGetErrorString8(rc));

    rc=IDirectSound_Compact(dso);
    ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));

    rc=IDirectSound_GetSpeakerConfig(dso,0);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
       "should have returned DSERR_INVALIDPARAM, returned: %s\n",
       DXGetErrorString8(rc));

    rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
    ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
       DXGetErrorString8(rc));

    speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
                                        DSSPEAKER_GEOMETRY_WIDE);
    rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
    ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
       DXGetErrorString8(rc));
    if (rc==DS_OK) {
        rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
        ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
           DXGetErrorString8(rc));
        if (rc==DS_OK && speaker_config!=new_speaker_config)
               trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
               "config: expected 0x%08lx, got 0x%08lx\n",
               speaker_config,new_speaker_config);
    }

EXIT:
    ref=IDirectSound_Release(dso);
    ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
}
Пример #17
0
/************************************************************************************
** Extract capabilities info from each device.
*/
static BOOL CALLBACK Pa_EnumProc(LPGUID lpGUID, 
				         LPCTSTR lpszDesc,
				         LPCTSTR lpszDrvName, 
				         LPVOID lpContext )
{
	HRESULT    hr;
	LPDIRECTSOUND          lpDirectSound;
#if SUPPORT_AUDIO_CAPTURE
	LPDIRECTSOUNDCAPTURE   lpDirectSoundCapture;
#endif /* SUPPORT_AUDIO_CAPTURE */
	int        isInput  = (int) lpContext;  /* Passed from Pa_CountDevices() */
	internalPortAudioDevice *pad;
		
	if( sDeviceIndex >= sNumDevices )
	{
		sEnumerationError = paInternalError;
		return FALSE;
	}
	pad = &sDevices[sDeviceIndex];
/* Copy GUID to static array. Set pointer. */
	if( lpGUID == NULL )
	{
		pad->pad_lpGUID = NULL;
	}
	else
	{
		memcpy( &pad->pad_GUID, lpGUID, sizeof(GUID) );
		pad->pad_lpGUID = &pad->pad_GUID;
	}
	pad->pad_Info.sampleRates = pad->pad_SampleRates;  /* Point to array. */
/* Allocate room for descriptive name. */
	if( lpszDesc != NULL )
	{
		int len = strlen(lpszDesc);
		pad->pad_Info.name = (char *)malloc( len+1 );
		if( pad->pad_Info.name == NULL )
		{
			sEnumerationError = paInsufficientMemory;
			return FALSE;
		}
		memcpy( (void *) pad->pad_Info.name, lpszDesc, len+1 );
	}
#if SUPPORT_AUDIO_CAPTURE
	if( isInput )
	{
	/********** Input ******************************/
		DSCCAPS     caps;
		if( lpGUID == NULL ) sDefaultInputDeviceID = sDeviceIndex;
		hr = DirectSoundCaptureCreate(  lpGUID, &lpDirectSoundCapture,   NULL );
		if( hr != DS_OK )
		{
			pad->pad_Info.maxInputChannels = 0;
			DBUG(("Cannot create Capture for %s. Result = 0x%x\n", lpszDesc, hr ));
		}
		else
		{
	/* Query device characteristics. */
			caps.dwSize = sizeof(caps);
			IDirectSoundCapture_GetCaps( lpDirectSoundCapture, &caps );
			/* printf("caps.dwFormats = 0x%x\n", caps.dwFormats ); */
			pad->pad_Info.maxInputChannels = caps.dwChannels;
	/* Determine sample rates from flags. */
			if( caps.dwChannels == 2 )
			{
				int index = 0;
				if( caps.dwFormats & WAVE_FORMAT_1S16) pad->pad_SampleRates[index++] = 11025.0;
				if( caps.dwFormats & WAVE_FORMAT_2S16) pad->pad_SampleRates[index++] = 22050.0;
				if( caps.dwFormats & WAVE_FORMAT_4S16) pad->pad_SampleRates[index++] = 44100.0;
				pad->pad_Info.numSampleRates = index;
			}
			else if( caps.dwChannels == 1 )
			{
				int index = 0;
				if( caps.dwFormats & WAVE_FORMAT_1M16) pad->pad_SampleRates[index++] = 11025.0;
				if( caps.dwFormats & WAVE_FORMAT_2M16) pad->pad_SampleRates[index++] = 22050.0;
				if( caps.dwFormats & WAVE_FORMAT_4M16) pad->pad_SampleRates[index++] = 44100.0;
				pad->pad_Info.numSampleRates = index;
			}
			else pad->pad_Info.numSampleRates = 0;
			IDirectSoundCapture_Release( lpDirectSoundCapture );
		}
	}
	else
#endif /* SUPPORT_AUDIO_CAPTURE */
	{
	/********** Output ******************************/
		DSCAPS     caps;
		if( lpGUID == NULL ) sDefaultOutputDeviceID = sDeviceIndex;
	/* Create interfaces for each object. */
		hr = DirectSoundCreate(  lpGUID, &lpDirectSound,   NULL );
		if( hr != DS_OK )
		{
			pad->pad_Info.maxOutputChannels = 0;
			DBUG(("Cannot create dsound for %s. Result = 0x%x\n", lpszDesc, hr ));
		}
		else
		{
		/* Query device characteristics. */
			caps.dwSize = sizeof(caps);
			IDirectSound_GetCaps( lpDirectSound, &caps );
			pad->pad_Info.maxOutputChannels = ( caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;
		/* Get sample rates. */
			pad->pad_SampleRates[0] = (double) caps.dwMinSecondarySampleRate;
			pad->pad_SampleRates[1] = (double) caps.dwMaxSecondarySampleRate;
			if( caps.dwFlags & DSCAPS_CONTINUOUSRATE ) pad->pad_Info.numSampleRates = -1;
			else if( caps.dwMinSecondarySampleRate == caps.dwMaxSecondarySampleRate )
			{
				if( caps.dwMinSecondarySampleRate == 0 )
				{
			/*
			** On my Thinkpad 380Z, DirectSoundV6 returns min-max=0 !!
			** But it supports continuous sampling.
			** So fake range of rates, and hope it really supports it.
			*/
					pad->pad_SampleRates[0] = 11025.0f;
					pad->pad_SampleRates[1] = 48000.0f;
					pad->pad_Info.numSampleRates = -1; /* continuous range */
					
					DBUG(("PA - Reported rates both zero. Setting to fake values for device #%d\n", sDeviceIndex ));
				}
				else
				{
					pad->pad_Info.numSampleRates = 1;
				}
			}
			else if( (caps.dwMinSecondarySampleRate < 1000.0) && (caps.dwMaxSecondarySampleRate > 50000.0) )
			{
			/* The EWS88MT drivers lie, lie, lie. The say they only support two rates, 100 & 100000.
			** But we know that they really support a range of rates!
			** So when we see a ridiculous set of rates, assume it is a range.
			*/
				pad->pad_Info.numSampleRates = -1;
				DBUG(("PA - Sample rate range used instead of two odd values for device #%d\n", sDeviceIndex ));
			}
			else pad->pad_Info.numSampleRates = 2;
			IDirectSound_Release( lpDirectSound );
		}
	}
	pad->pad_Info.nativeSampleFormats = paInt16;
	sDeviceIndex++;
	return( TRUE );
}
Пример #18
0
/*
 * Test the primary buffer at different formats while keeping the
 * secondary buffer at a constant format.
 */
static HRESULT test_primary_secondary(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND dso=NULL;
    LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
    DSBUFFERDESC bufdesc;
    DSCAPS dscaps;
    WAVEFORMATEX wfx, wfx2;
    int f,ref;

    /* Create the DirectSound object */
    rc=DirectSoundCreate(lpGuid,&dso,NULL);
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
       "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
    if (rc!=DS_OK)
        return rc;

    /* Get the device capabilities */
    ZeroMemory(&dscaps, sizeof(dscaps));
    dscaps.dwSize=sizeof(dscaps);
    rc=IDirectSound_GetCaps(dso,&dscaps);
    ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
    if (rc!=DS_OK)
        goto EXIT;

    /* We must call SetCooperativeLevel before creating primary buffer */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
       DXGetErrorString8(rc));
    if (rc!=DS_OK)
        goto EXIT;

    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DS_OK && primary!=NULL,
       "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
       "%s\n",DXGetErrorString8(rc));

    if (rc==DS_OK && primary!=NULL) {
        for (f=0;f<NB_FORMATS;f++) {
            /* We must call SetCooperativeLevel to be allowed to call
             * SetFormat */
            /* DSOUND: Setting DirectSound cooperative level to
             * DSSCL_PRIORITY */
            rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
            ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
               DXGetErrorString8(rc));
            if (rc!=DS_OK)
                goto EXIT;

            init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
                        formats[f][2]);
            wfx2=wfx;
            rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
            ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %s\n",
               format_string(&wfx), DXGetErrorString8(rc));

            /* There is no garantee that SetFormat will actually change the
             * format to what we asked for. It depends on what the soundcard
             * supports. So we must re-query the format.
             */
            rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
            ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
               DXGetErrorString8(rc));
            if (rc==DS_OK &&
                (wfx.wFormatTag!=wfx2.wFormatTag ||
                 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
                 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
                 wfx.nChannels!=wfx2.nChannels)) {
                trace("Requested primary format tag=0x%04x %ldx%dx%d "
                      "avg.B/s=%ld align=%d\n",
                      wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
                      wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
                trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
                      wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
                      wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
            }

            /* Set the CooperativeLevel back to normal */
            /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
            rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
            ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
               DXGetErrorString8(rc));

            init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);

            secondary=NULL;
            ZeroMemory(&bufdesc, sizeof(bufdesc));
            bufdesc.dwSize=sizeof(bufdesc);
            bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
            bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
                                        wfx.nBlockAlign);
            bufdesc.lpwfxFormat=&wfx2;
            if (winetest_interactive) {
                trace("  Testing a primary buffer at %ldx%dx%d with a "
                      "secondary buffer at %ldx%dx%d\n",
                      wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
                      wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
            }
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DS_OK && secondary!=NULL,
               "IDirectSound_CreateSoundBuffer() failed to create a secondary "
               "buffer %s\n",DXGetErrorString8(rc));

            if (rc==DS_OK && secondary!=NULL) {
                test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
                            winetest_interactive,1.0,0,NULL,0,0,FALSE,0);

                ref=IDirectSoundBuffer_Release(secondary);
                ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
                   "should have 0\n",ref);
            }
        }

        ref=IDirectSoundBuffer_Release(primary);
        ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
           "should have 0\n",ref);
    }

    /* Set the CooperativeLevel back to normal */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
    ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
       DXGetErrorString8(rc));

EXIT:
    ref=IDirectSound_Release(dso);
    ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
    if (ref!=0)
        return DSERR_GENERIC;

    return rc;
}
Пример #19
0
static int dx_init(const char *param, int *speed, int *fragsize, int *fragnr,
                   int *channels)
{
HRESULT result;

    DEBUG(("DirectSound driver initialization: speed = %d, fragsize = %d, fragnr = %d, channels = %d\n",
           *speed, *fragsize, *fragnr, *channels));

    if (ds == NULL) {
        result = DirectSoundCreate(NULL, &ds, NULL);
        if (result != DS_OK) {
            ui_error("Cannot initialize DirectSound:\n%s", ds_error(result));
            return -1;
        }

        result = IDirectSound_SetCooperativeLevel(ds, ui_get_main_hwnd(),
                                                  DSSCL_EXCLUSIVE);
        if (result != DS_OK) {
            ui_error("Cannot set cooperative level:\n%s",
                     ds_error(result));
            return -1;
        }
    }

    memset(&capabilities, 0, sizeof(DSCAPS));
    capabilities.dwSize = sizeof(DSCAPS);

    IDirectSound_GetCaps(ds, &capabilities);
    if ((capabilities.dwFlags & DSCAPS_PRIMARY16BIT)
        || (capabilities.dwFlags & DSCAPS_SECONDARY16BIT)) {
        is16bit = 1;
    } else {
        is16bit = 0;
    }
    if (!((capabilities.dwFlags & DSCAPS_PRIMARYSTEREO)
        || (capabilities.dwFlags & DSCAPS_SECONDARYSTEREO))) {
        *channels = 1;
    }
    num_of_channels = *channels;

    DEBUG(("16bit flag: %d",is16bit));
    DEBUG(("Channels: %d",*channels));
    DEBUG(("Capabilities %08x",capabilities.dwFlags));
    DEBUG(("Secondary min Hz: %d",capabilities.dwMinSecondarySampleRate));
    DEBUG(("Secondary max Hz: %d",capabilities.dwMaxSecondarySampleRate));

    memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
    pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
    pcmwf.wf.nChannels = *channels;
    pcmwf.wf.nSamplesPerSec = *speed;
    pcmwf.wBitsPerSample = is16bit ? 16 : 8;
/* Hack to fix if mmsystem header is bad
    ((WORD*)&pcmwf)[7] = 16;
*/
    pcmwf.wf.nBlockAlign = (is16bit ? 2 : 1) * *channels;
    pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;

    memset(&desc, 0, sizeof(DSBUFFERDESC));
    desc.dwSize = sizeof(DSBUFFERDESC);
    desc.dwFlags = DSBCAPS_PRIMARYBUFFER;

    fragment_size = *fragsize; /* frames */
    buffer_size = *fragsize * *fragnr * (is16bit ? 2 : 1) * *channels; /* bytes */
    stream_buffer_size = fragment_size * *fragnr * *channels; /* nr of samples */
    buffer_offset = 0; /* bytes */
    
    result = IDirectSound_CreateSoundBuffer(ds, &desc, &pbuffer, NULL);

    if (result != DS_OK) {
        ui_error("Cannot create Primary DirectSound bufer: %s",
                 ds_error(result));
        return -1;
    }

    memset(&desc, 0, sizeof(DSBUFFERDESC));
    desc.dwSize = sizeof(DSBUFFERDESC);
    desc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2
                   | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN
                   | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS ;

    desc.dwBufferBytes = buffer_size;
    desc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;

    result = IDirectSound_CreateSoundBuffer(ds, &desc, &buffer, NULL);
    if (result != DS_OK) {
        ui_error("Cannot create DirectSound buffer:\n%s", ds_error(result));
        return -1;
    }

    memset(&wfex, 0, sizeof(WAVEFORMATEX));
    wfex.wFormatTag = WAVE_FORMAT_PCM;
    wfex.nChannels = *channels;
    wfex.nSamplesPerSec = *speed;
    wfex.wBitsPerSample = is16bit ? 16 : 8;
    wfex.nBlockAlign = (is16bit ? 2 : 1) * *channels;
    wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;

    result=IDirectSoundBuffer_SetFormat(pbuffer, &wfex);
    if (result != DS_OK) {
        ui_error("Cannot set Output format for primary sound buffer:\n%s",
                 ds_error(result));
        return -1;
    }

    dx_clear();
    /* Let's go...  */
    result = IDirectSoundBuffer_Play(buffer, 0, 0, DSBPLAY_LOOPING);
    if (result == DSERR_BUFFERLOST) {
        ui_error("Restoring DirectSound buffer.");
        if ((result = IDirectSoundBuffer_Restore(buffer)) != DS_OK)
            ui_error("Cannot restore buffer:\n%s", ds_error(result));
        result = IDirectSoundBuffer_Play(buffer, 0, 0, DSBPLAY_LOOPING);
    }
    if (result != DS_OK) {
        ui_error("Cannot play DirectSound buffer:\n%s", ds_error(result));
        return -1;
    }

    DEBUG(("DirectSound initialization done succesfully.\n"));

    return 0;
}
Пример #20
0
/*
 * new_fluid_dsound_audio_driver
 */
fluid_audio_driver_t*
new_fluid_dsound_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
  HRESULT hr;
  DSBUFFERDESC desc;
  fluid_dsound_audio_driver_t* dev = NULL;
  DSCAPS caps;
  char *buf1;
  DWORD bytes1;
  double sample_rate;
  int periods, period_size;
  fluid_dsound_devsel_t devsel;

  /* check if the globals are initialized */
  if (FLUID_HINSTANCE == NULL) {
    FLUID_LOG(FLUID_ERR, "FluidSynth hinstance not set, which is needed for DirectSound");
    return NULL;
  }

/*
  if (fluid_wnd == NULL) {
    if (fluid_win32_create_window() != 0) {
      FLUID_LOG(FLUID_ERR, "Couldn't create window needed for DirectSound");
      return NULL;
    }
  }
*/
  /* create and clear the driver data */
  dev = FLUID_NEW(fluid_dsound_audio_driver_t);
  if (dev == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }
  FLUID_MEMSET(dev, 0, sizeof(fluid_dsound_audio_driver_t));

  dev->synth = synth;
  dev->cont = 1;

  fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
  fluid_settings_getint(settings, "audio.periods", &periods);
  fluid_settings_getint(settings, "audio.period-size", &period_size);

  /* check the format */
  if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
    FLUID_LOG(FLUID_ERR, "Unhandled sample format");
    goto error_recovery;
  }

  dev->frame_size = 2 * sizeof(short);
  dev->buffer_byte_size = period_size * dev->frame_size;
  dev->queue_byte_size = periods * dev->buffer_byte_size;
  dev->write = fluid_synth_write_s16;

  /* create and initialize the buffer format */
  dev->format = (WAVEFORMATEX*) FLUID_MALLOC(sizeof(WAVEFORMATEX));
  if (dev->format == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    goto error_recovery;
  }
  ZeroMemory(dev->format, sizeof(WAVEFORMATEX));

  dev->format->wFormatTag = WAVE_FORMAT_PCM;
  dev->format->nChannels = 2;
  dev->format->wBitsPerSample = 16;
  dev->format->nSamplesPerSec = (DWORD) sample_rate;
  dev->format->nBlockAlign = (WORD) dev->frame_size;
  dev->format->nAvgBytesPerSec = dev->format->nSamplesPerSec * dev->frame_size;
  dev->format->cbSize = 0;

  devsel.devGUID = NULL;
  /* get the selected device name. if none is specified, use NULL for the default device. */
  if(fluid_settings_dupstr(settings, "audio.dsound.device", &devsel.devname) == FLUID_OK /* ++ alloc device name */
     && devsel.devname && strlen (devsel.devname) > 0) {
    /* look for the GUID of the selected device */
    DirectSoundEnumerate((LPDSENUMCALLBACK) fluid_dsound_enum_callback2, (void *)&devsel);
  }

  if (devsel.devname) FLUID_FREE (devsel.devname);      /* -- free device name */

  /* open DirectSound */
  hr = DirectSoundCreate(devsel.devGUID, &dev->direct_sound, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to create the DirectSound object");
    goto error_recovery;
  }

  hr = IDirectSound_SetCooperativeLevel(dev->direct_sound, fluid_win32_get_window(), DSSCL_PRIORITY);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to set the cooperative level");
    goto error_recovery;
  }

  caps.dwSize = sizeof(caps);
  hr = IDirectSound_GetCaps(dev->direct_sound, &caps);
  if (hr != DS_OK)  {
    FLUID_LOG(FLUID_ERR, "Failed to query the device capacities");
    goto error_recovery;
  }

  /* create primary buffer */

  ZeroMemory(&desc, sizeof(DSBUFFERDESC));
  desc.dwSize = sizeof(DSBUFFERDESC);
  desc.dwFlags = DSBCAPS_PRIMARYBUFFER;

  if (caps.dwFreeHwMixingStreamingBuffers > 0) {
    desc.dwFlags |= DSBCAPS_LOCHARDWARE;
  }

  hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->prim_buffer, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to allocate the primary buffer");
    goto error_recovery;
  }

  /* set the primary sound buffer to this format. if it fails, just
     print a warning. */
  hr = IDirectSoundBuffer_SetFormat(dev->prim_buffer, dev->format);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_WARN, "Can't set format of primary sound buffer", fluid_win32_error(hr));
  }

  /* initialize the buffer description */

  ZeroMemory(&desc, sizeof(DSBUFFERDESC));
  desc.dwSize = sizeof(DSBUFFERDESC);
  desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
  desc.lpwfxFormat = dev->format;
  desc.dwBufferBytes = dev->queue_byte_size;
  desc.dwReserved = 0;

  if (caps.dwFreeHwMixingStreamingBuffers > 0) {
    desc.dwFlags |= DSBCAPS_LOCHARDWARE;
  }

  /* create the secondary sound buffer */

  hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->sec_buffer, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "dsound: Can't create sound buffer: %s", fluid_win32_error(hr));
    goto error_recovery;
  }


  /* Lock */
  hr = IDirectSoundBuffer_Lock(dev->sec_buffer, 0, 0, (void*) &buf1, &bytes1, 0, 0, DSBLOCK_ENTIREBUFFER);

  if ((hr != DS_OK) || (buf1 == NULL)) {
    FLUID_LOG(FLUID_PANIC, "Failed to lock the audio buffer. Exiting.");
    goto error_recovery;
  }

  /* fill the buffer with silence */
  memset(buf1, 0, bytes1);

  /* Unlock */
  IDirectSoundBuffer_Unlock(dev->sec_buffer, buf1, bytes1, 0, 0);


  /* start the audio thread */
  dev->thread = CreateThread(NULL, 0, &fluid_dsound_audio_run, (LPVOID) dev, 0, &dev->threadID);
  if (dev->thread == NULL) {
    goto error_recovery;
  }

  return (fluid_audio_driver_t*) dev;

 error_recovery:
  delete_fluid_dsound_audio_driver((fluid_audio_driver_t*) dev);
  return NULL;
}