예제 #1
0
파일: directsound.c 프로젝트: videolan/vlc
/**
 * Creates a PCM DirectSound buffer.
 *
 * We first try to create a WAVE_FORMAT_IEEE_FLOAT buffer if supported by
 * the hardware, otherwise we create a WAVE_FORMAT_PCM buffer.
 */
static HRESULT CreateDSBufferPCM( vlc_object_t *obj, aout_stream_sys_t *sys,
                                  vlc_fourcc_t *i_format, int i_channels,
                                  int i_rate, bool b_probe )
{
    HRESULT hr;
    unsigned i_nb_channels = vlc_popcount( i_channels );

    if( var_GetBool( obj, "directx-audio-float32" ) )
    {
        hr = CreateDSBuffer( obj, sys, VLC_CODEC_FL32, i_channels,
                             i_nb_channels, i_rate, b_probe );
        if( hr == DS_OK )
        {
            *i_format = VLC_CODEC_FL32;
            return DS_OK;
        }
    }

    hr = CreateDSBuffer( obj, sys, VLC_CODEC_S16N, i_channels, i_nb_channels,
                         i_rate, b_probe );
    if( hr == DS_OK )
    {
        *i_format = VLC_CODEC_S16N;
        return DS_OK;
    }

    return hr;
}
예제 #2
0
HRESULT CMpcAudioRenderer::CompleteConnect(IPin *pReceivePin)
{
    HRESULT			hr = S_OK;
    TRACE(_T("CMpcAudioRenderer::CompleteConnect\n"));

    if (!m_useWASAPI && ! m_pDS) {
        return E_FAIL;
    }

    if (SUCCEEDED(hr)) {
        hr = CBaseRenderer::CompleteConnect(pReceivePin);
    }
    if (SUCCEEDED(hr)) {
        hr = InitCoopLevel();
    }

    if (!m_useWASAPI) {
        if (SUCCEEDED(hr)) {
            hr = CreateDSBuffer();
        }
    }
    if (SUCCEEDED(hr)) {
        TRACE(_T("CMpcAudioRenderer::CompleteConnect Success\n"));
    }
    return hr;
}
예제 #3
0
AUI_ERRCODE aui_DirectSound::Load( void )
{
    aui_SoundFormat *   format = static_cast<aui_SoundFormat *>(m_format);
	Assert(format);
	if (!format) return AUI_ERRCODE_INVALIDPARAM;

	if (m_data) return AUI_ERRCODE_OK;

	if (AUI_ERRCODE_OK == format->LoadSoundData(m_filename, &m_data, &m_size))
	{
		if (!CreateDSBuffer())
		{
        	LPVOID  pMem1;
            LPVOID  pMem2;
	        DWORD   dwSize1;
            DWORD   dwSize2;
	        HRESULT hr  = dsb->Lock(0, m_size, &pMem1, &dwSize1, &pMem2, &dwSize2, 0);

            if (DS_OK == hr)
            {
                CopyMemory(pMem1, m_data, m_size);
                hr = dsb->Unlock(pMem1, dwSize1, pMem2, dwSize2);
            }

            if (DS_OK != hr)
            {
                return AUI_ERRCODE_MEMALLOCFAILED;
            }
		}

        format->ReleaseSoundData();
	}

	return AUI_ERRCODE_OK;
}
예제 #4
0
HRESULT CMpcAudioRenderer::CompleteConnect(IPin *pReceivePin)
{
	HRESULT			hr = S_OK;

 if (!useWASAPI && ! m_pDS) return E_FAIL;

	if (SUCCEEDED(hr)) hr = CBaseRenderer::CompleteConnect(pReceivePin);
	if (SUCCEEDED(hr)) hr = InitCoopLevel();

 if (useWASAPI)
 {
  if (SUCCEEDED(hr) && !pRenderClient) hr = InitDevice(pAudioClient, m_pWaveFileFormat, &pRenderClient);
 }
	else
 {
  if (SUCCEEDED(hr)) hr = CreateDSBuffer();
 }

	return hr;

}
예제 #5
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;
}
예제 #6
0
//===========================================================================
// DS_Load
//===========================================================================
void DS_Load(sfxbuffer_t *buf, struct sfxsample_s *sample)
{
#define SAMPLE_SILENCE	16		// Samples to interpolate to silence.
#define SAMPLE_ROUNDOFF	32		// The length is a multiple of this.
	LPDIRECTSOUNDBUFFER newSound = NULL;
	LPDIRECTSOUND3DBUFFER newSound3D = NULL;
	bool play3d = !!(buf->flags & SFXBF_3D);
	void *writePtr1 = NULL, *writePtr2 = NULL;
	DWORD writeBytes1, writeBytes2;
	unsigned int safeNumSamples = sample->numsamples + SAMPLE_SILENCE;
	unsigned int safeSize, i;
	int last, delta;

	// Does the buffer already have a sample loaded?
	if(buf->sample)
	{	
		// Is the same one?
		if(buf->sample->id == sample->id) return; 
	}

	// The safe number of samples is rounded to the next highest 
	// count of SAMPLE_ROUNDOFF.
	if((i = safeNumSamples % SAMPLE_ROUNDOFF) != 0)
	{
		safeNumSamples += SAMPLE_ROUNDOFF - i;
/*#if _DEBUG
		Con_Message("Safelen = %i\n", safeNumSamples);
#endif*/
	}
	safeSize = safeNumSamples * sample->bytesper;
/*#if _DEBUG
	Con_Message("Safesize = %i\n", safeSize);
#endif*/

	// If a sample has already been loaded, unload it.
	FreeDSBuffers(buf);

	// Create the DirectSound buffer. Its length will match the sample 
	// exactly.
	if(FAILED(hr = CreateDSBuffer(DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY 
		| DSBCAPS_STATIC | (play3d? DSBCAPS_CTRL3D 
		| DSBCAPS_MUTE3DATMAXDISTANCE : DSBCAPS_CTRLPAN),
		safeNumSamples, buf->freq, buf->bytes*8, 1, &newSound)))
	{
		if(verbose) Error("DS_Load", "Couldn't create a new buffer.");
		return;
	}
	if(play3d)
	{
		// Query the 3D interface.
		if(FAILED(hr = newSound->QueryInterface(IID_IDirectSound3DBuffer, 
			(void**) &newSound3D)))
		{
			if(verbose) Error("DS_Load", "Couldn't get 3D buffer interface.");
			newSound->Release();
			return;
		}
	}

	// Lock and load!
	newSound->Lock(0, 0, &writePtr1, &writeBytes1, 
		&writePtr2, &writeBytes2, DSBLOCK_ENTIREBUFFER);
	if(writePtr2 && verbose) Error("DS_Load", "Unexpected buffer lock behavior.");

	// Copy the sample data.
	memcpy(writePtr1, sample->data, sample->size);

	/*Con_Message("Fill %i bytes (orig=%i).\n", safeSize - sample->size,
			sample->size);*/

	// Interpolate to silence.
	// numSafeSamples includes at least SAMPLE_ROUNDOFF extra samples.
	last = sample->bytesper==1? ((byte*)sample->data)[sample->numsamples - 1]
		: ((short*)sample->data)[sample->numsamples - 1];
	delta = sample->bytesper==1? 0x80 - last : -last;
	//Con_Message("last = %i\n", last);
	for(i = 0; i < safeNumSamples - sample->numsamples; i++)
	{
		float pos = i/(float)SAMPLE_SILENCE;
		if(pos > 1) pos = 1;
		if(sample->bytesper == 1) // 8-bit sample.
		{
			((byte*)writePtr1)[sample->numsamples + i] = 
				byte( last + delta*pos );
		}
		else // 16-bit sample.
		{
			((short*)writePtr1)[sample->numsamples + i] = 
				short( last + delta*pos );
		}
	}

	// Unlock the buffer.
	newSound->Unlock(writePtr1, writeBytes1, writePtr2, writeBytes2);

	buf->ptr = newSound;
	buf->ptr3d = newSound3D;
	buf->sample = sample;
}
예제 #7
0
//===========================================================================
// DS_Init
//===========================================================================
int DS_Init(void)
{
	HWND				hWnd;
	DSBUFFERDESC		desc;
	LPDIRECTSOUNDBUFFER	bufTemp;

	if(initOk) return true;

	// Are we in verbose mode?	
	if((verbose = ArgExists("-verbose")))
		Con_Message("DS_Init(Compat): Initializing sound driver...\n");

	// Get Doomsday's window handle.
	hWnd = (HWND) DD_GetInteger(DD_WINDOW_HANDLE);

	hr = DS_OK;
	if(ArgExists("-noeax") 
		|| FAILED(hr = EAXDirectSoundCreate(NULL, &dsound, NULL)))
	{
		// EAX can't be initialized. Use normal DS, then.
		if(FAILED(hr)) Error("DS_Init", "EAX 2 couldn't be initialized.");
		if(FAILED(hr = DirectSoundCreate(NULL, &dsound, NULL)))
		{
			Error("DS_Init", "Failed to create dsound interface.");
			return false;
		}
	}
	// Set the cooperative level.
	if(FAILED(hr = dsound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY)))
	{
		Error("DS_Init", "Couldn't set dSound coop level.");
		return false;
	}
	// Get the primary buffer and the listener.
	primary = NULL;
	memset(&desc, 0, sizeof(desc));
	desc.dwSize = sizeof(desc);
	desc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
	dsListener = NULL;
	if(SUCCEEDED(dsound->CreateSoundBuffer(&desc, &primary, NULL)))
	{
		// Query the listener interface.
		primary->QueryInterface(IID_IDirectSound3DListener, 
			(void**) &dsListener);
	}
	else
	{
		// Failure; get a 2D primary buffer, then.
		desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
		dsound->CreateSoundBuffer(&desc, &primary, NULL);
	}
	// Start playing the primary buffer.
	if(primary) 
	{
		if(FAILED(hr = primary->Play(0, 0, DSBPLAY_LOOPING)))
			Error("DS_Init", "Can't play primary buffer.");
	}
	
	// Try to get the EAX listener property set. 
	// Create a temporary secondary buffer for it.
	eaxListener = NULL;
	if(SUCCEEDED(CreateDSBuffer(DSBCAPS_STATIC | DSBCAPS_CTRL3D, 
		DSBSIZE_MIN, 22050, 8, 1, &bufTemp)))
	{
		// Now try to get the property set.
		if(SUCCEEDED(hr = bufTemp->QueryInterface(IID_IKsPropertySet, 
			(void**) &eaxListener)))
		{
			DWORD support = 0, revsize = 0;
			// Check for support.
			if(FAILED(hr = eaxListener->QuerySupport(
				DSPROPSETID_EAX_ListenerProperties,
				DSPROPERTY_EAXLISTENER_ENVIRONMENT,
				&support)) 
				|| ((support & NEEDED_SUPPORT) != NEEDED_SUPPORT))
			{
				Error("DS_Init", "Sufficient EAX2 support not present.");
				eaxListener->Release();
				eaxListener = NULL;
			}
			else
			{
				// EAX is supported!
				if(verbose) Con_Message("DS_Init(Compat): EAX2 is available.\n");
			}
		}
		// Release the temporary buffer interface.
		bufTemp->Release();
	}
		
	// Get the caps.
	dsCaps.dwSize = sizeof(dsCaps);
	dsound->GetCaps(&dsCaps);
	if(verbose) Con_Message("DS_Init(Compat): Number of hardware 3D "
		"buffers: %i\n", dsCaps.dwMaxHw3DAllBuffers);

	// Configure the DS3D listener.
	if(dsListener)
	{
		dsListener->SetDistanceFactor(1/36.0f, DS3D_DEFERRED);
		dsListener->SetDopplerFactor(2, DS3D_DEFERRED);
	}

	// Success!
	initOk = true;
	return true;
}
예제 #8
0
int I2_PlaySound(void *data, boolean play3d, sound3d_t *desc, int pan)
{
	sampleheader_t	*header = data;
	byte			*sample = (byte*) data + sizeof(sampleheader_t);
	sndsource_t		*sndbuf;
	void			*writePtr1=NULL, *writePtr2=NULL;
	DWORD			writeBytes1, writeBytes2;
	int				samplelen = header->length, freq = header->frequency, bits = 8;

	// Can we play sounds?
	if(!initOk || data == NULL) return 0;	// Sorry...

	if(snd_Resample != 1 && snd_Resample != 2 && snd_Resample != 4)
	{
		ST_Message("I2_PlaySound: invalid resample factor.\n");
		snd_Resample = 1;
	}

	// Get a buffer that's doing nothing.
	sndbuf = I2_GetFreeSource(play3d);
	sndbuf->startTime = I_GetTime();
	// Prepare the audio data.
	if(snd_Resample == 1 && !snd_16bits) // Play sounds as normal?
	{
		// No resampling necessary.
		sndbuf->freq = header->frequency;
	}
	else
	{
		// Resample the sound.
		sample = I_Resample8bitSound(sample, header->length, freq, 
			snd_Resample, snd_16bits, &samplelen);
		if(snd_16bits) bits = 16;
		freq *= snd_Resample;
		sndbuf->freq = freq;
	}
	if(sndbuf->source)
	{
		// Release the old source.
		I2_KillSource(sndbuf);
	}
	// Create a new source.
	if(FAILED(hr = CreateDSBuffer(play3d? DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY 
		| DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE | DSBCAPS_STATIC 
		: DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY 
		| DSBCAPS_STATIC, 
		header->length * snd_Resample, freq, bits, 1, &sndbuf->source)))
	{
		ST_Message("I2_PlaySound: couldn't create a new buffer (result = %d).\n", hr & 0xffff);
		memset(sndbuf, 0, sizeof(*sndbuf));
		return 0;
	}
	if(play3d)
	{
		// Query the 3D interface.
		if(FAILED(hr = IDirectSoundBuffer_QueryInterface(sndbuf->source, &IID_IDirectSound3DBuffer, 
			&sndbuf->source3D)))
		{
			ST_Message("I2_PlaySound: couldn't get 3D buffer interface (result = %d).\n", hr & 0xffff);
			IDirectSoundBuffer_Release(sndbuf->source);
			memset(sndbuf, 0, sizeof(*sndbuf));
			return 0;
		}
	}

	// Lock the buffer.
	if(FAILED(hr = IDirectSoundBuffer_Lock(sndbuf->source, 0, samplelen, 
		&writePtr1, &writeBytes1, &writePtr2, &writeBytes2, 0)))
	{
		I_Error("I2_PlaySound: couldn't lock source (result = %d).\n", hr & 0xffff);
	}

	// Copy the data over.
	memcpy(writePtr1, sample, writeBytes1);
	if(writePtr2) memcpy(writePtr2, (char*) sample + writeBytes1, writeBytes2);

	// Unlock the buffer.
	if(FAILED(hr = IDirectSoundBuffer_Unlock(sndbuf->source, writePtr1, writeBytes1, 
		writePtr2, writeBytes2)))
	{
		I_Error("I2_PlaySound: couldn't unlock source (result = %d).\n", hr & 0xffff);
		return 0;
	}

	if(play3d)
	{
		// Set the 3D parameters of the source.
		if(desc->flags & DDSOUNDF_VERY_LOUD)
		{
			// You can hear this from very far away (e.g. thunderclap).
			IDirectSound3DBuffer_SetMinDistance(sndbuf->source3D, 10000, DS3D_DEFERRED);
			IDirectSound3DBuffer_SetMaxDistance(sndbuf->source3D, 20000, DS3D_DEFERRED);	
		}
		else
		{
			IDirectSound3DBuffer_SetMinDistance(sndbuf->source3D, 100, DS3D_DEFERRED);
			IDirectSound3DBuffer_SetMaxDistance(sndbuf->source3D, MAX_SND_DIST, DS3D_DEFERRED);
		}
		if(desc->flags & DDSOUNDF_LOCAL)
			IDirectSound3DBuffer_SetMode(sndbuf->source3D, DS3DMODE_DISABLE, DS3D_DEFERRED);
	}
	else
	{
		// If playing in 2D mode, set the pan.
		I2_SetPan(sndbuf, pan/1000.0f);
	}
	I2_UpdateSource(sndbuf, desc);
	// Start playing the buffer.
	if(FAILED(hr = IDirectSoundBuffer_Play(sndbuf->source, 0, 0, 0)))
	{
		I_Error("I2_PlaySound: couldn't start source (result = %d).\n", hr & 0xffff);
		return 0;
	}
	// Return the handle to the sound source.
	return (sndbuf->id = idGen++);
}