HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt) { HRESULT err = DSERR_BUFFERLOST; int i; WAVEFORMATEX *old_fmt; WAVEFORMATEXTENSIBLE *fmtex; BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY); TRACE("(%p,%p)\n", device, passed_fmt); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (passed_fmt == NULL) { WARN("invalid parameter: passed_fmt==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", passed_fmt->wFormatTag, passed_fmt->nChannels, passed_fmt->nSamplesPerSec, passed_fmt->nAvgBytesPerSec, passed_fmt->nBlockAlign, passed_fmt->wBitsPerSample, passed_fmt->cbSize); /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); old_fmt = device->pwfx; device->pwfx = DSOUND_CopyFormat(passed_fmt); fmtex = (WAVEFORMATEXTENSIBLE *)device->pwfx; if (device->pwfx == NULL) { device->pwfx = old_fmt; old_fmt = NULL; err = DSERR_OUTOFMEMORY; goto done; } DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; /* requested format failed, so try others */ if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT){ device->pwfx->wFormatTag = WAVE_FORMAT_PCM; device->pwfx->wBitsPerSample = 32; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; } if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE && IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)){ fmtex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; device->pwfx->wBitsPerSample = 32; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; } device->pwfx->wBitsPerSample = 32; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 16; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 8; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->nChannels = (passed_fmt->nChannels == 2) ? 1 : 2; device->pwfx->wBitsPerSample = passed_fmt->wBitsPerSample; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 32; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 16; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; device->pwfx->wBitsPerSample = 8; device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign; device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8); err = DSOUND_ReopenDevice(device, FALSE); if(SUCCEEDED(err)) goto opened; WARN("No formats could be opened\n"); goto done; opened: err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { WARN("DSOUND_PrimaryOpen failed\n"); goto done; } if (passed_fmt->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer) { DSOUND_PrimaryClose(device); device->pwfx->nSamplesPerSec = passed_fmt->nSamplesPerSec; err = DSOUND_ReopenDevice(device, TRUE); if (FAILED(err)) WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err); else if (FAILED((err = DSOUND_PrimaryOpen(device)))) WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err); } device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen); device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len); FillMemory(device->mix_buffer, device->mix_buffer_len, 0); device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1]; device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1]; if (old_fmt->nSamplesPerSec != device->pwfx->nSamplesPerSec || old_fmt->wBitsPerSample != device->pwfx->wBitsPerSample || old_fmt->nChannels != device->pwfx->nChannels) { IDirectSoundBufferImpl** dsb = device->buffers; for (i = 0; i < device->nrofbuffers; i++, dsb++) { /* **** */ RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE); (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec; DSOUND_RecalcFormat((*dsb)); DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE); (*dsb)->primary_mixpos = 0; RtlReleaseResource(&(*dsb)->lock); /* **** */ } } done: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ HeapFree(GetProcessHeap(), 0, old_fmt); return err; }
static HRESULT IDirectSoundCaptureBufferImpl_Create( DirectSoundCaptureDevice *device, IDirectSoundCaptureBufferImpl ** ppobj, LPCDSCBUFFERDESC lpcDSCBufferDesc) { LPWAVEFORMATEX wfex; IDirectSoundCaptureBufferImpl *This; TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc); if (ppobj == NULL) { WARN("invalid parameter: ppobj == NULL\n"); return DSERR_INVALIDPARAM; } *ppobj = NULL; if (!device) { WARN("not initialized\n"); return DSERR_UNINITIALIZED; } if (lpcDSCBufferDesc == NULL) { WARN("invalid parameter: lpcDSCBufferDesc == NULL\n"); return DSERR_INVALIDPARAM; } if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) && (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) || (lpcDSCBufferDesc->dwBufferBytes == 0) || (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { /* FIXME: DSERR_BADFORMAT ? */ WARN("invalid lpcDSCBufferDesc\n"); return DSERR_INVALIDPARAM; } wfex = lpcDSCBufferDesc->lpwfxFormat; TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, wfex->nAvgBytesPerSec, wfex->nBlockAlign, wfex->wBitsPerSample, wfex->cbSize); device->pwfx = DSOUND_CopyFormat(wfex); if ( device->pwfx == NULL ) return DSERR_OUTOFMEMORY; This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureBufferImpl)); if ( This == NULL ) { WARN("out of memory\n"); return DSERR_OUTOFMEMORY; } else { HRESULT err = DS_OK; LPBYTE newbuf; DWORD buflen; This->numIfaces = 0; This->ref = 0; This->refn = 0; This->device = device; This->device->capture_buffer = This; This->nrofnotifies = 0; This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, lpcDSCBufferDesc->dwSize); if (This->pdscbd) CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize); else { WARN("no memory\n"); This->device->capture_buffer = 0; HeapFree( GetProcessHeap(), 0, This ); return DSERR_OUTOFMEMORY; } This->IDirectSoundCaptureBuffer8_iface.lpVtbl = &dscbvt; This->IDirectSoundNotify_iface.lpVtbl = &dscnvt; err = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, (void**)&device->client); if(FAILED(err)){ WARN("Activate failed: %08x\n", err); HeapFree(GetProcessHeap(), 0, This->pdscbd); This->device->capture_buffer = 0; HeapFree( GetProcessHeap(), 0, This ); return err; } err = IAudioClient_Initialize(device->client, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST, 200 * 100000, 50000, device->pwfx, NULL); if(FAILED(err)){ WARN("Initialize failed: %08x\n", err); IAudioClient_Release(device->client); device->client = NULL; HeapFree(GetProcessHeap(), 0, This->pdscbd); This->device->capture_buffer = 0; HeapFree( GetProcessHeap(), 0, This ); if(err == AUDCLNT_E_UNSUPPORTED_FORMAT) return DSERR_BADFORMAT; return err; } err = IAudioClient_GetService(device->client, &IID_IAudioCaptureClient, (void**)&device->capture); if(FAILED(err)){ WARN("GetService failed: %08x\n", err); IAudioClient_Release(device->client); device->client = NULL; HeapFree(GetProcessHeap(), 0, This->pdscbd); This->device->capture_buffer = 0; HeapFree( GetProcessHeap(), 0, This ); return err; } buflen = lpcDSCBufferDesc->dwBufferBytes; TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer); if (device->buffer) newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen); else newbuf = HeapAlloc(GetProcessHeap(),0,buflen); if (newbuf == NULL) { IAudioClient_Release(device->client); device->client = NULL; IAudioCaptureClient_Release(device->capture); device->capture = NULL; HeapFree(GetProcessHeap(), 0, This->pdscbd); This->device->capture_buffer = 0; HeapFree( GetProcessHeap(), 0, This ); return DSERR_OUTOFMEMORY; } device->buffer = newbuf; device->buflen = buflen; } IDirectSoundCaptureBuffer_AddRef(&This->IDirectSoundCaptureBuffer8_iface); *ppobj = This; TRACE("returning DS_OK\n"); return DS_OK; }
HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt) { HRESULT err = S_OK; WAVEFORMATEX *old_fmt; WAVEFORMATEXTENSIBLE *fmtex, *passed_fmtex = (WAVEFORMATEXTENSIBLE*)passed_fmt; TRACE("(%p,%p)\n", device, passed_fmt); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (passed_fmt == NULL) { WARN("invalid parameter: passed_fmt==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", passed_fmt->wFormatTag, passed_fmt->nChannels, passed_fmt->nSamplesPerSec, passed_fmt->nAvgBytesPerSec, passed_fmt->nBlockAlign, passed_fmt->wBitsPerSample, passed_fmt->cbSize); if(passed_fmt->wBitsPerSample < 8 || passed_fmt->wBitsPerSample % 8 != 0 || passed_fmt->nChannels == 0 || passed_fmt->nSamplesPerSec == 0 || passed_fmt->nAvgBytesPerSec == 0 || passed_fmt->nBlockAlign != passed_fmt->nChannels * passed_fmt->wBitsPerSample / 8) return DSERR_INVALIDPARAM; if(passed_fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){ if(passed_fmtex->Samples.wValidBitsPerSample > passed_fmtex->Format.wBitsPerSample) return DSERR_INVALIDPARAM; } /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); old_fmt = device->primary_pwfx; device->primary_pwfx = DSOUND_CopyFormat(passed_fmt); fmtex = (WAVEFORMATEXTENSIBLE *)device->primary_pwfx; if (device->primary_pwfx == NULL) { err = DSERR_OUTOFMEMORY; goto out; } if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && fmtex->Samples.wValidBitsPerSample == 0) { TRACE("Correcting 0 valid bits per sample\n"); fmtex->Samples.wValidBitsPerSample = fmtex->Format.wBitsPerSample; } if(device->priolevel == DSSCL_WRITEPRIMARY || device->nrofbuffers == 0) err = DSOUND_ReopenDevice(device, TRUE); if (FAILED(err) && device->priolevel == DSSCL_WRITEPRIMARY) { ERR("No formats could be opened\n"); HeapFree(GetProcessHeap(), 0, device->primary_pwfx); device->primary_pwfx = old_fmt; } else { /* ignore failures */ err = S_OK; HeapFree(GetProcessHeap(), 0, old_fmt); } out: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ return err; }
static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client, BOOL forcewave, WAVEFORMATEX **wfx) { WAVEFORMATEXTENSIBLE *retwfe = NULL; WAVEFORMATEX *w; HRESULT hr; if (!forcewave) { WAVEFORMATEXTENSIBLE *mixwfe; hr = IAudioClient_GetMixFormat(client, (WAVEFORMATEX**)&mixwfe); if (FAILED(hr)) return hr; if (mixwfe->Format.nChannels < device->num_speakers) { device->speaker_config = DSOUND_FindSpeakerConfig(device->mmdevice, mixwfe->Format.nChannels); DSOUND_ParseSpeakerConfig(device); } else if (mixwfe->Format.nChannels > device->num_speakers) { mixwfe->Format.nChannels = device->num_speakers; mixwfe->Format.nBlockAlign = mixwfe->Format.nChannels * mixwfe->Format.wBitsPerSample / 8; mixwfe->Format.nAvgBytesPerSec = mixwfe->Format.nSamplesPerSec * mixwfe->Format.nBlockAlign; mixwfe->dwChannelMask = speaker_config_to_channel_mask(device->speaker_config); } if (!IsEqualGUID(&mixwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) { WAVEFORMATEXTENSIBLE testwfe = *mixwfe; testwfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; testwfe.Samples.wValidBitsPerSample = testwfe.Format.wBitsPerSample = 32; testwfe.Format.nBlockAlign = testwfe.Format.nChannels * testwfe.Format.wBitsPerSample / 8; testwfe.Format.nAvgBytesPerSec = testwfe.Format.nSamplesPerSec * testwfe.Format.nBlockAlign; if (FAILED(IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &testwfe.Format, (WAVEFORMATEX**)&retwfe))) w = DSOUND_CopyFormat(&mixwfe->Format); else if (retwfe) w = DSOUND_CopyFormat(&retwfe->Format); else w = DSOUND_CopyFormat(&testwfe.Format); CoTaskMemFree(retwfe); retwfe = NULL; } else w = DSOUND_CopyFormat(&mixwfe->Format); CoTaskMemFree(mixwfe); } else if (device->primary_pwfx->wFormatTag == WAVE_FORMAT_PCM || device->primary_pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { WAVEFORMATEX *wi = device->primary_pwfx; WAVEFORMATEXTENSIBLE *wfe; /* Convert to WAVEFORMATEXTENSIBLE */ w = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE)); wfe = (WAVEFORMATEXTENSIBLE*)w; if (!wfe) return DSERR_OUTOFMEMORY; wfe->Format = *wi; w->wFormatTag = WAVE_FORMAT_EXTENSIBLE; w->cbSize = sizeof(*wfe) - sizeof(*w); w->nBlockAlign = w->nChannels * w->wBitsPerSample / 8; w->nAvgBytesPerSec = w->nSamplesPerSec * w->nBlockAlign; wfe->dwChannelMask = 0; if (wi->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { w->wBitsPerSample = 32; wfe->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; } else wfe->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfe->Samples.wValidBitsPerSample = w->wBitsPerSample; } else w = DSOUND_CopyFormat(device->primary_pwfx); if (!w) return DSERR_OUTOFMEMORY; hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, w, (WAVEFORMATEX**)&retwfe); if (retwfe) { memcpy(w, retwfe, sizeof(WAVEFORMATEX) + retwfe->Format.cbSize); CoTaskMemFree(retwfe); } if (FAILED(hr)) { WARN("IsFormatSupported failed: %08x\n", hr); HeapFree(GetProcessHeap(), 0, w); return hr; } *wfx = w; return S_OK; }
static HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, BOOL forced) { HRESULT err = DSERR_BUFFERLOST; int i; DWORD nSamplesPerSec, bpp, chans; LPWAVEFORMATEX oldpwfx; TRACE("(%p,%p)\n", device, wfex); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (wfex == NULL) { WARN("invalid parameter: wfex==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, wfex->nAvgBytesPerSec, wfex->nBlockAlign, wfex->wBitsPerSample, wfex->cbSize); /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); nSamplesPerSec = device->pwfx->nSamplesPerSec; bpp = device->pwfx->wBitsPerSample; chans = device->pwfx->nChannels; oldpwfx = device->pwfx; device->pwfx = DSOUND_CopyFormat(wfex); if (device->pwfx == NULL) { device->pwfx = oldpwfx; oldpwfx = NULL; err = DSERR_OUTOFMEMORY; goto done; } if (!(device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) && device->hwbuf) { err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx); /* On bad format, try to re-create, big chance it will work then, only do this if we <HAVE> to */ if (forced && (device->pwfx->nSamplesPerSec/100 != wfex->nSamplesPerSec/100 || err == DSERR_BADFORMAT)) { DWORD cp_size = wfex->wFormatTag == WAVE_FORMAT_PCM ? sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX) + wfex->cbSize; err = DSERR_BUFFERLOST; CopyMemory(device->pwfx, wfex, cp_size); } if (err != DSERR_BUFFERLOST && FAILED(err)) { DWORD size = DSOUND_GetFormatSize(oldpwfx); WARN("IDsDriverBuffer_SetFormat failed\n"); if (!forced) { CopyMemory(device->pwfx, oldpwfx, size); err = DS_OK; } goto done; } if (err == S_FALSE) { /* ALSA specific: S_FALSE tells that recreation was successful, * but size and location may be changed, and buffer has to be restarted * I put it here, so if frequency doesn't match the error will be changed to DSERR_BUFFERLOST * and the entire re-initialization will occur anyway */ IDsDriverBuffer_Lock(device->hwbuf, (LPVOID *)&device->buffer, &device->buflen, NULL, NULL, 0, 0, DSBLOCK_ENTIREBUFFER); IDsDriverBuffer_Unlock(device->hwbuf, device->buffer, 0, NULL, 0); if (device->state == STATE_PLAYING) device->state = STATE_STARTING; else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED; device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0; err = DS_OK; } DSOUND_RecalcPrimary(device); } if (err == DSERR_BUFFERLOST) { DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, FALSE); if (FAILED(err)) { WARN("DSOUND_ReopenDevice failed: %08x\n", err); goto done; } err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { WARN("DSOUND_PrimaryOpen failed\n"); goto done; } if (wfex->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer) { DSOUND_PrimaryClose(device); device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec; err = DSOUND_ReopenDevice(device, TRUE); if (FAILED(err)) WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err); else if (FAILED((err = DSOUND_PrimaryOpen(device)))) WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err); } } device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen); device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len); FillMemory(device->mix_buffer, device->mix_buffer_len, 0); device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1]; device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1]; if (nSamplesPerSec != device->pwfx->nSamplesPerSec || bpp != device->pwfx->wBitsPerSample || chans != device->pwfx->nChannels) { IDirectSoundBufferImpl** dsb = device->buffers; for (i = 0; i < device->nrofbuffers; i++, dsb++) { /* **** */ RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE); (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec; DSOUND_RecalcFormat((*dsb)); DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE); (*dsb)->primary_mixpos = 0; RtlReleaseResource(&(*dsb)->lock); /* **** */ } } done: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ HeapFree(GetProcessHeap(), 0, oldpwfx); return err; }
HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt) { HRESULT err = S_OK; WAVEFORMATEX *old_fmt; WAVEFORMATEXTENSIBLE *fmtex, *passed_fmtex = (WAVEFORMATEXTENSIBLE*)passed_fmt; BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY); TRACE("(%p,%p)\n", device, passed_fmt); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (passed_fmt == NULL) { WARN("invalid parameter: passed_fmt==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", passed_fmt->wFormatTag, passed_fmt->nChannels, passed_fmt->nSamplesPerSec, passed_fmt->nAvgBytesPerSec, passed_fmt->nBlockAlign, passed_fmt->wBitsPerSample, passed_fmt->cbSize); if(passed_fmt->wBitsPerSample < 8 || passed_fmt->wBitsPerSample % 8 != 0 || passed_fmt->nChannels == 0 || passed_fmt->nSamplesPerSec == 0 || passed_fmt->nAvgBytesPerSec == 0 || passed_fmt->nBlockAlign != passed_fmt->nChannels * passed_fmt->wBitsPerSample / 8) return DSERR_INVALIDPARAM; if(passed_fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){ if(passed_fmtex->Samples.wValidBitsPerSample > passed_fmtex->Format.wBitsPerSample) return DSERR_INVALIDPARAM; } /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); if (device->priolevel == DSSCL_WRITEPRIMARY) { old_fmt = device->primary_pwfx; device->primary_pwfx = DSOUND_CopyFormat(passed_fmt); fmtex = (WAVEFORMATEXTENSIBLE *)device->primary_pwfx; if (device->primary_pwfx == NULL) { err = DSERR_OUTOFMEMORY; goto out; } if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && fmtex->Samples.wValidBitsPerSample == 0) { TRACE("Correcting 0 valid bits per sample\n"); fmtex->Samples.wValidBitsPerSample = fmtex->Format.wBitsPerSample; } DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, forced); if (FAILED(err)) { ERR("No formats could be opened\n"); goto done; } err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { ERR("DSOUND_PrimaryOpen failed\n"); goto done; } done: if (err != DS_OK) device->primary_pwfx = old_fmt; else HeapFree(GetProcessHeap(), 0, old_fmt); } else if (passed_fmt->wFormatTag == WAVE_FORMAT_PCM || passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { /* Fill in "real" values to primary_pwfx */ WAVEFORMATEX *fmt = device->primary_pwfx; *fmt = *device->pwfx; fmtex = (void*)device->pwfx; if (IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) && passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { fmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT; } else { fmt->wFormatTag = WAVE_FORMAT_PCM; fmt->wBitsPerSample = 16; } fmt->nBlockAlign = fmt->nChannels * fmt->wBitsPerSample / 8; fmt->nAvgBytesPerSec = fmt->nBlockAlign * fmt->nSamplesPerSec; fmt->cbSize = 0; } else { device->primary_pwfx = HeapReAlloc(GetProcessHeap(), 0, device->primary_pwfx, sizeof(*fmtex)); memcpy(device->primary_pwfx, device->pwfx, sizeof(*fmtex)); } out: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ return err; }
HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex) { HRESULT err = DSERR_BUFFERLOST; int i; DWORD nSamplesPerSec, bpp, chans; LPWAVEFORMATEX oldpwfx; BOOL forced = device->priolevel == DSSCL_WRITEPRIMARY; TRACE("(%p,%p)\n", device, wfex); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } /* Let's be pedantic! */ if (wfex == NULL) { WARN("invalid parameter: wfex==NULL!\n"); return DSERR_INVALIDPARAM; } TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, wfex->nAvgBytesPerSec, wfex->nBlockAlign, wfex->wBitsPerSample, wfex->cbSize); /* **** */ RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); nSamplesPerSec = device->pwfx->nSamplesPerSec; bpp = device->pwfx->wBitsPerSample; chans = device->pwfx->nChannels; oldpwfx = device->pwfx; device->pwfx = DSOUND_CopyFormat(wfex); if (device->pwfx == NULL) { device->pwfx = oldpwfx; oldpwfx = NULL; err = DSERR_OUTOFMEMORY; goto done; } DSOUND_PrimaryClose(device); err = DSOUND_ReopenDevice(device, FALSE); if (FAILED(err)) { WARN("DSOUND_ReopenDevice failed: %08x\n", err); goto done; } err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { WARN("DSOUND_PrimaryOpen failed\n"); goto done; } if (wfex->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer) { DSOUND_PrimaryClose(device); device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec; err = DSOUND_ReopenDevice(device, TRUE); if (FAILED(err)) WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err); else if (FAILED((err = DSOUND_PrimaryOpen(device)))) WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err); } device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen); device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len); FillMemory(device->mix_buffer, device->mix_buffer_len, 0); device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1]; device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1]; if (nSamplesPerSec != device->pwfx->nSamplesPerSec || bpp != device->pwfx->wBitsPerSample || chans != device->pwfx->nChannels) { IDirectSoundBufferImpl** dsb = device->buffers; for (i = 0; i < device->nrofbuffers; i++, dsb++) { /* **** */ RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE); (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec; DSOUND_RecalcFormat((*dsb)); DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE); (*dsb)->primary_mixpos = 0; RtlReleaseResource(&(*dsb)->lock); /* **** */ } } done: LeaveCriticalSection(&(device->mixlock)); RtlReleaseResource(&(device->buffer_list_lock)); /* **** */ HeapFree(GetProcessHeap(), 0, oldpwfx); return err; }