/** * 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; }
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; }
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; }
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; }
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; }
//=========================================================================== // 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; }
//=========================================================================== // 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; }
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++); }