Example #1
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;
}
Example #2
0
/*
====================
SndSys_Init

Create "snd_renderbuffer" with the proper sound format if the call is successful
May return a suggested format if the requested format isn't available
====================
*/
qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
{
	unsigned int buffersize;
	SDL_AudioSpec wantspec;
	SDL_AudioSpec obtainspec;

	snd_threaded = false;

	Con_DPrint ("SndSys_Init: using the SDL module\n");

	// Init the SDL Audio subsystem
	if( SDL_InitSubSystem( SDL_INIT_AUDIO ) ) {
		Con_Print( "Initializing the SDL Audio subsystem failed!\n" );
		return false;
	}

	buffersize = (unsigned int)ceil((double)requested->speed / 25.0); // 2048 bytes on 24kHz to 48kHz

	// Init the SDL Audio subsystem
	wantspec.callback = Buffer_Callback;
	wantspec.userdata = NULL;
	wantspec.freq = requested->speed;
	wantspec.format = ((requested->width == 1) ? AUDIO_U8 : AUDIO_S16SYS);
	wantspec.channels = requested->channels;
	wantspec.samples = CeilPowerOf2(buffersize);  // needs to be a power of 2 on some platforms.

	Con_Printf("Wanted audio Specification:\n"
				"\tChannels  : %i\n"
				"\tFormat    : 0x%X\n"
				"\tFrequency : %i\n"
				"\tSamples   : %i\n",
				wantspec.channels, wantspec.format, wantspec.freq, wantspec.samples);

	if( SDL_OpenAudio( &wantspec, &obtainspec ) )
	{
		Con_Printf( "Failed to open the audio device! (%s)\n", SDL_GetError() );
		return false;
	}

	Con_Printf("Obtained audio specification:\n"
				"\tChannels  : %i\n"
				"\tFormat    : 0x%X\n"
				"\tFrequency : %i\n"
				"\tSamples   : %i\n",
				obtainspec.channels, obtainspec.format, obtainspec.freq, obtainspec.samples);

	// If we haven't obtained what we wanted
	if (wantspec.freq != obtainspec.freq ||
		wantspec.format != obtainspec.format ||
		wantspec.channels != obtainspec.channels)
	{
		SDL_CloseAudio();

		// Pass the obtained format as a suggested format
		if (suggested != NULL)
		{
			suggested->speed = obtainspec.freq;
			// FIXME: check the format more carefully. There are plenty of unsupported cases
			suggested->width = ((obtainspec.format == AUDIO_U8) ? 1 : 2);
			suggested->channels = obtainspec.channels;
		}

		return false;
	}

	snd_threaded = true;

	snd_renderbuffer = Snd_CreateRingBuffer(requested, 0, NULL);
	if (snd_channellayout.integer == SND_CHANNELLAYOUT_AUTO)
		Cvar_SetValueQuick (&snd_channellayout, SND_CHANNELLAYOUT_STANDARD);

	sdlaudiotime = 0;
	SDL_PauseAudio( false );

	return true;
}
Example #3
-1
/*
==================
SndSys_InitMmsystem

Crappy windows multimedia base
==================
*/
static qboolean SndSys_InitMmsystem (const snd_format_t* requested)
{
	WAVEFORMATEXTENSIBLE format;
	int				i;
	HRESULT			hr;

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

	// Open a waveform device for output using window callback
	while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, (WAVEFORMATEX*)&format,
					0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR)
	{
		if (hr != MMSYSERR_ALLOCATED)
		{
			Con_Print("waveOutOpen failed\n");
			return false;
		}

		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("waveOutOpen failure;\n  hardware already in use\n");
			return false;
		}
	}

	wav_buffer_size = bound(128, snd_wav_partitionsize.integer, 8192) * requested->channels * requested->width;

	/*
	 * Allocate and lock memory for the waveform data. The memory
	 * for waveform data must be globally allocated with
	 * GMEM_MOVEABLE and GMEM_SHARE flags.
	 */
	gSndBufSize = WAV_BUFFERS * wav_buffer_size;
	hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize);
	if (!hData)
	{
		Con_Print("Sound: Out of memory.\n");
		SndSys_Shutdown ();
		return false;
	}
	lpData = (HPSTR)GlobalLock(hData);
	if (!lpData)
	{
		Con_Print("Sound: Failed to lock.\n");
		SndSys_Shutdown ();
		return false;
	}
	memset (lpData, 0, gSndBufSize);

	/*
	 * Allocate and lock memory for the header. This memory must
	 * also be globally allocated with GMEM_MOVEABLE and
	 * GMEM_SHARE flags.
	 */
	hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS);

	if (hWaveHdr == NULL)
	{
		Con_Print("Sound: Failed to Alloc header.\n");
		SndSys_Shutdown ();
		return false;
	}

	lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);

	if (lpWaveHdr == NULL)
	{
		Con_Print("Sound: Failed to lock header.\n");
		SndSys_Shutdown ();
		return false;
	}

	memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);

	// After allocation, set up and prepare headers
	for (i=0 ; i<WAV_BUFFERS ; i++)
	{
		lpWaveHdr[i].dwBufferLength = wav_buffer_size;
		lpWaveHdr[i].lpData = lpData + i * wav_buffer_size;

		if (waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)) != MMSYSERR_NOERROR)
		{
			Con_Print("Sound: failed to prepare wave headers\n");
			SndSys_Shutdown ();
			return false;
		}
	}

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

	prev_painted = 0;
	paintpot = 0;

	snd_sent = 0;
	snd_completed = 0;

	wav_init = true;

	return true;
}