static void xaudio2_free(xaudio2_t *handle) { if (!handle) return; if (handle->pSourceVoice) { IXAudio2SourceVoice_Stop(handle->pSourceVoice, 0, XAUDIO2_COMMIT_NOW); IXAudio2SourceVoice_DestroyVoice(handle->pSourceVoice); } if (handle->pMasterVoice) { IXAudio2MasteringVoice_DestroyVoice(handle->pMasterVoice); } if (handle->pXAudio2) { IXAudio2_Release(handle->pXAudio2); } if (handle->hEvent) CloseHandle(handle->hEvent); free(handle->buf); #if defined(__cplusplus) && !defined(CINTERFACE) delete handle; #else free(handle); #endif }
static void XAUDIO2_CloseDevice(_THIS) { if (this->hidden != NULL) { IXAudio2 *ixa2 = this->hidden->ixa2; IXAudio2SourceVoice *source = this->hidden->source; IXAudio2MasteringVoice *mastering = this->hidden->mastering; if (source != NULL) { IXAudio2SourceVoice_Stop(source, 0, XAUDIO2_COMMIT_NOW); IXAudio2SourceVoice_FlushSourceBuffers(source); IXAudio2SourceVoice_DestroyVoice(source); } if (ixa2 != NULL) { IXAudio2_StopEngine(ixa2); } if (mastering != NULL) { IXAudio2MasteringVoice_DestroyVoice(mastering); } if (ixa2 != NULL) { IXAudio2_Release(ixa2); } SDL_free(this->hidden->mixbuf); if (this->hidden->semaphore != NULL) { SDL_DestroySemaphore(this->hidden->semaphore); } SDL_free(this->hidden); this->hidden = NULL; } }
gc_result gaX_device_close_xaudio2(ga_DeviceImpl_XAudio2* in_device) { gc_int32 i; if(in_device->source) { IXAudio2SourceVoice_Stop(in_device->source, 0, XAUDIO2_COMMIT_NOW); IXAudio2SourceVoice_FlushSourceBuffers(in_device->source); IXAudio2SourceVoice_DestroyVoice(in_device->source); } if(in_device->xa) IXAudio2_StopEngine(in_device->xa); if(in_device->master) IXAudio2MasteringVoice_DestroyVoice(in_device->master); if(in_device->xa) IXAudio2_Release(in_device->xa); CoUninitialize(); for(i = 0; i < in_device->numBuffers; ++i) gcX_ops->freeFunc(in_device->buffers[i]); gcX_ops->freeFunc(in_device->buffers); in_device->devType = GA_DEVICE_TYPE_UNKNOWN; in_device->source = 0; in_device->master = 0; in_device->xa = 0; gcX_ops->freeFunc(in_device); return GC_SUCCESS; }
static UINT32 check_has_devices(IXAudio2 *xa) { HRESULT hr; IXAudio2MasteringVoice *master; hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects); if(hr != S_OK) return 0; IXAudio2MasteringVoice_DestroyVoice(master); return 1; }
void snd_stop(void) { xaudio2.opened = FALSE; if (xaudio2.source) { IXAudio2SourceVoice_Stop(xaudio2.source, 0, XAUDIO2_COMMIT_NOW); IXAudio2SourceVoice_FlushSourceBuffers(xaudio2.source); IXAudio2SourceVoice_DestroyVoice(xaudio2.source); xaudio2.source = NULL; } if (xaudio2.engine) { IXAudio2_StopEngine(xaudio2.engine); } if (xaudio2.master) { IXAudio2MasteringVoice_DestroyVoice(xaudio2.master); xaudio2.master = NULL; } if (xaudio2.engine) { IXAudio2_Release(xaudio2.engine); xaudio2.engine = NULL; } if (snd.cache) { if (SNDCACHE->start) { free(SNDCACHE->start); } if (SNDCACHE->silence) { free(SNDCACHE->silence); } if (xaudio2.semaphore) { CloseHandle(xaudio2.semaphore); xaudio2.semaphore = NULL; } snd.cache = NULL; } if (audio_channels_quit) { audio_channels_quit(); } if (audio_quality_quit) { audio_quality_quit(); } }
void xaudio2_free(xaudio2_t *handle) { if (handle) { if (handle->pSourceVoice) { IXAudio2SourceVoice_Stop(handle->pSourceVoice, 0, XAUDIO2_COMMIT_NOW); IXAudio2SourceVoice_DestroyVoice(handle->pSourceVoice); } if (handle->pMasterVoice) IXAudio2MasteringVoice_DestroyVoice(handle->pMasterVoice); if (handle->pXAudio2) IXAudio2_Release(handle->pXAudio2); if (handle->hEvent) CloseHandle(handle->hEvent); free(handle->buf); free(handle); } }
static void XAudio2_Exit(void) { if (UpdateBufferHandle != NULL) { /* signal thread to exit and wait for the exit */ if (threadInUse) { threadInUse = 0; MUTEX_UNLOCK(vars); SetEvent(hBufferEvent); WaitForSingleObject(UpdateBufferHandle, INFINITE); MUTEX_LOCK(vars); } CloseHandle(UpdateBufferHandle); UpdateBufferHandle = NULL; } IXAudio2SourceVoice_Stop(pSourceVoice, 0, 0); if (pSourceVoice) { IXAudio2SourceVoice_DestroyVoice(pSourceVoice); pSourceVoice = NULL; } if (pMasterVoice) { IXAudio2MasteringVoice_DestroyVoice(pMasterVoice); pMasterVoice = NULL; } if (pXAudio2) { IXAudio2_Release(pXAudio2); pXAudio2 = NULL; } #ifndef __cplusplus if (hBufferEvent != NULL) { CloseHandle(hBufferEvent); hBufferEvent = NULL; } #endif #ifndef _XBOX CoUninitialize(); #endif VC_Exit(); }
ga_DeviceImpl_XAudio2* gaX_device_open_xaudio2(gc_int32 in_numBuffers, gc_int32 in_numSamples, ga_Format* in_format) { ga_DeviceImpl_XAudio2* ret = gcX_ops->allocFunc(sizeof(ga_DeviceImpl_XAudio2)); HRESULT result; WAVEFORMATEX fmt; gc_int32 i; ret->devType = GA_DEVICE_TYPE_XAUDIO2; ret->numBuffers = in_numBuffers; ret->numSamples = in_numSamples; memcpy(&ret->format, in_format, sizeof(ga_Format)); ret->sampleSize = ga_format_sampleSize(in_format); ret->nextBuffer = 0; ret->xa = 0; ret->master = 0; CoInitializeEx(NULL, COINIT_MULTITHREADED); result = XAudio2Create(&ret->xa, 0, XAUDIO2_DEFAULT_PROCESSOR); if(FAILED(result)) goto cleanup; result = IXAudio2_CreateMasteringVoice(ret->xa, &ret->master, 2, 44100, 0, 0, 0); if(FAILED(result)) goto cleanup; fmt.cbSize = sizeof(WAVEFORMATEX); ZeroMemory(&fmt, sizeof(WAVEFORMATEX)); fmt.cbSize = sizeof(WAVEFORMATEX); fmt.wFormatTag = WAVE_FORMAT_PCM; fmt.nChannels = 2; fmt.wBitsPerSample = 16; fmt.nSamplesPerSec = 44100; fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8); fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; result = IXAudio2_CreateSourceVoice(ret->xa, &ret->source, &fmt, XAUDIO2_VOICE_NOPITCH, XAUDIO2_DEFAULT_FREQ_RATIO, 0, 0, 0); if(FAILED(result)) goto cleanup; result =IXAudio2_StartEngine(ret->xa); if(FAILED(result)) goto cleanup; result = IXAudio2SourceVoice_Start(ret->source, 0, XAUDIO2_COMMIT_NOW); if(FAILED(result)) goto cleanup; ret->buffers = gcX_ops->allocFunc(ret->numBuffers * sizeof(void*)); for(i = 0; i < ret->numBuffers; ++i) ret->buffers[i] = gcX_ops->allocFunc(ret->numSamples * ret->sampleSize); return ret; cleanup: if(ret->source) { IXAudio2SourceVoice_Stop(ret->source, 0, XAUDIO2_COMMIT_NOW); IXAudio2SourceVoice_FlushSourceBuffers(ret->source); IXAudio2SourceVoice_DestroyVoice(ret->source); } if(ret->xa) IXAudio2_StopEngine(ret->xa); if(ret->master) IXAudio2MasteringVoice_DestroyVoice(ret->master); if(ret->xa) IXAudio2_Release(ret->xa); CoUninitialize(); gcX_ops->freeFunc(ret); return 0; }
static void test_buffer_callbacks(IXAudio2 *xa) { HRESULT hr; IXAudio2MasteringVoice *master; IXAudio2SourceVoice *src; WAVEFORMATEX fmt; XAUDIO2_BUFFER buf; XAUDIO2_VOICE_STATE state; struct vcb_buf_testdata testdata[5]; int i; obs_calls = 0; obe_calls = 0; XA2CALL_0V(StopEngine); if(xaudio27) hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL); else hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects); ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr); fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; fmt.nChannels = 2; fmt.nSamplesPerSec = 44100; fmt.wBitsPerSample = 32; fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; fmt.cbSize = 0; XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &vcb_buf, NULL, NULL); ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr); memset(&buf, 0, sizeof(buf)); buf.AudioBytes = 4410 * fmt.nBlockAlign; buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes); fill_buf((float*)buf.pAudioData, &fmt, 440, 4410); /* submit same buffer fragment 5 times */ for(i = 0; i < 5; ++i){ testdata[i].idx = i; testdata[i].src = src; buf.pContext = &testdata[i]; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); } hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW); ok(hr == S_OK, "Start failed: %08x\n", hr); XA2CALL_0(StartEngine); ok(hr == S_OK, "StartEngine failed: %08x\n", hr); while(1){ if(xaudio27) IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state); else IXAudio2SourceVoice_GetState(src, &state, 0); if(state.SamplesPlayed >= 4410 * 5) break; Sleep(100); } ok(state.SamplesPlayed == 4410 * 5, "Got wrong samples played\n"); HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData); if(xaudio27) IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src); else IXAudio2SourceVoice_DestroyVoice(src); IXAudio2MasteringVoice_DestroyVoice(master); }
static void test_simple_streaming(IXAudio2 *xa) { HRESULT hr; IXAudio2MasteringVoice *master; IXAudio2SourceVoice *src, *src2; IUnknown *vumeter; WAVEFORMATEX fmt; XAUDIO2_BUFFER buf, buf2; XAUDIO2_VOICE_STATE state; XAUDIO2_EFFECT_DESCRIPTOR effect; XAUDIO2_EFFECT_CHAIN chain; memset(&ecb_state, 0, sizeof(ecb_state)); memset(&src1_state, 0, sizeof(src1_state)); memset(&src2_state, 0, sizeof(src2_state)); XA2CALL_0V(StopEngine); /* Tests show in native XA2.8, ECB is called from a mixer thread, but VCBs * may be called from other threads in any order. So we can't rely on any * sequencing between VCB calls. * * XA2.7 does all mixing from a single thread, so call sequence can be * tested. */ XA2CALL(RegisterForCallbacks, &ecb); ok(hr == S_OK, "RegisterForCallbacks failed: %08x\n", hr); if(xaudio27) hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL); else hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects); ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr); /* create first source voice */ fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; fmt.nChannels = 2; fmt.nSamplesPerSec = 44100; fmt.wBitsPerSample = 32; fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; fmt.cbSize = 0; XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &vcb1, NULL, NULL); ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr); memset(&buf, 0, sizeof(buf)); buf.AudioBytes = 22050 * fmt.nBlockAlign; buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes); fill_buf((float*)buf.pAudioData, &fmt, 440, 22050); hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW); ok(hr == S_OK, "Start failed: %08x\n", hr); /* create second source voice */ XA2CALL(CreateSourceVoice, &src2, &fmt, 0, 1.f, &vcb2, NULL, NULL); ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr); memset(&buf2, 0, sizeof(buf2)); buf2.AudioBytes = 22050 * fmt.nBlockAlign; buf2.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf2.AudioBytes); fill_buf((float*)buf2.pAudioData, &fmt, 220, 22050); hr = IXAudio2SourceVoice_SubmitSourceBuffer(src2, &buf2, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); hr = IXAudio2SourceVoice_Start(src2, 0, XAUDIO2_COMMIT_NOW); ok(hr == S_OK, "Start failed: %08x\n", hr); XA2CALL_0(StartEngine); ok(hr == S_OK, "StartEngine failed: %08x\n", hr); /* hook up volume meter */ if(xaudio27){ hr = CoCreateInstance(&CLSID_AudioVolumeMeter, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&vumeter); ok(hr == S_OK, "CoCreateInstance(AudioVolumeMeter) failed: %08x\n", hr); }else{ hr = pCreateAudioVolumeMeter(&vumeter); ok(hr == S_OK, "CreateAudioVolumeMeter failed: %08x\n", hr); } effect.InitialState = TRUE; effect.OutputChannels = 2; effect.pEffect = vumeter; chain.EffectCount = 1; chain.pEffectDescriptors = &effect; hr = IXAudio2MasteringVoice_SetEffectChain(master, &chain); ok(hr == S_OK, "SetEffectchain failed: %08x\n", hr); IUnknown_Release(vumeter); while(1){ if(xaudio27) IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state); else IXAudio2SourceVoice_GetState(src, &state, 0); if(state.SamplesPlayed >= 22050) break; Sleep(100); } ok(state.SamplesPlayed == 22050, "Got wrong samples played\n"); HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData); HeapFree(GetProcessHeap(), 0, (void*)buf2.pAudioData); if(xaudio27){ IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src); IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src2); }else{ IXAudio2SourceVoice_DestroyVoice(src); IXAudio2SourceVoice_DestroyVoice(src2); } IXAudio2MasteringVoice_DestroyVoice(master); XA2CALL_V(UnregisterForCallbacks, &ecb); }
static int XAudio2_Init(void) { UINT32 flags; DWORD thread_id; WAVEFORMATEX wfmt; memset(&wfmt, 0, sizeof(WAVEFORMATEX)); wfmt.wFormatTag= (md_mode & DMODE_FLOAT)? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM; wfmt.nChannels = (md_mode & DMODE_STEREO)? 2: 1; wfmt.nSamplesPerSec = md_mixfreq; wfmt.wBitsPerSample = (md_mode & DMODE_FLOAT)? 32: (md_mode & DMODE_16BITS)? 16: 8; wfmt.nBlockAlign = (wfmt.wBitsPerSample * wfmt.nChannels) / 8; wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign; if (wfmt.nSamplesPerSec < XAUDIO2_MIN_SAMPLE_RATE || wfmt.nSamplesPerSec > XAUDIO2_MAX_SAMPLE_RATE || wfmt.nChannels > XAUDIO2_MAX_AUDIO_CHANNELS) { return 1; } current_buf = 0; flags = 0; #if defined(_DEBUG) && !defined(DRV_XAUDIO28) /* flags |= XAUDIO2_DEBUG_ENGINE;*/ #endif #ifndef _XBOX CoInitializeEx(NULL, COINIT_MULTITHREADED); #endif if (FAILED(XAudio2Create(&pXAudio2, flags, XAUDIO2_DEFAULT_PROCESSOR))) { goto fail; } #if defined(DRV_XAUDIO28) if (FAILED(IXAudio2_CreateMasteringVoice(pXAudio2, &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, NULL, NULL, AudioCategory_Other))) { goto fail; } #else if (FAILED(IXAudio2_CreateMasteringVoice(pXAudio2, &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, 0, NULL))) { goto fail; } #endif if (FAILED(IXAudio2_CreateSourceVoice(pXAudio2, &pSourceVoice, &wfmt, 0, 1.0f, pcbVoice, NULL, NULL))) { goto fail; } #ifndef __cplusplus if ((hBufferEvent = CreateEvent(NULL, FALSE, FALSE, "libmikmod XAudio2 Driver buffer Event")) == NULL) { goto fail; } #endif if ((UpdateBufferHandle = CreateThread(NULL, 0, UpdateBufferProc, NULL, CREATE_SUSPENDED, &thread_id)) == NULL) { goto fail; } #if defined HAVE_SSE2 /* this test only works on Windows XP or later */ if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) { md_mode|=DMODE_SIMDMIXER; } #endif return VC_Init(); fail: if (pSourceVoice) { IXAudio2SourceVoice_DestroyVoice(pSourceVoice); pSourceVoice = NULL; } if (pMasterVoice) { IXAudio2MasteringVoice_DestroyVoice(pMasterVoice); pMasterVoice = NULL; } if (pXAudio2) { IXAudio2_Release(pXAudio2); pXAudio2 = NULL; } #ifndef _XBOX CoUninitialize(); #endif return 1; }
static void test_looping(IXAudio2 *xa) { HRESULT hr; IXAudio2MasteringVoice *master; IXAudio2SourceVoice *src; WAVEFORMATEX fmt; XAUDIO2_BUFFER buf; UINT32 played, running_total = 0; XA2CALL_0V(StopEngine); if(xaudio27) hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL); else hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects); ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr); fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; fmt.nChannels = 2; fmt.nSamplesPerSec = 44100; fmt.wBitsPerSample = 32; fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; fmt.cbSize = 0; XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &loop_buf, NULL, NULL); ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr); memset(&buf, 0, sizeof(buf)); buf.AudioBytes = 44100 * fmt.nBlockAlign; buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes); fill_buf((float*)buf.pAudioData, &fmt, 440, 44100); XA2CALL_0(StartEngine); ok(hr == S_OK, "StartEngine failed: %08x\n", hr); /* play from middle to end */ buf.PlayBegin = 22050; buf.PlayLength = 0; buf.LoopBegin = 0; buf.LoopLength = 0; buf.LoopCount = 0; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); played = play_to_completion(src, -1); ok(played - running_total == 22050, "Got wrong samples played: %u\n", played - running_total); running_total = played; ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends); /* play 4410 samples from middle */ buf.PlayBegin = 22050; buf.PlayLength = 4410; buf.LoopBegin = 0; buf.LoopLength = 0; buf.LoopCount = 0; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); played = play_to_completion(src, -1); ok(played - running_total == 4410, "Got wrong samples played: %u\n", played - running_total); running_total = played; ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends); /* loop 4410 samples in middle */ buf.PlayBegin = 0; buf.PlayLength = 0; buf.LoopBegin = 22050; buf.LoopLength = 4410; buf.LoopCount = 1; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); played = play_to_completion(src, -1); ok(played - running_total == 44100 + 4410, "Got wrong samples played: %u\n", played - running_total); running_total = played; ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends); /* play last half, then loop the whole buffer */ buf.PlayBegin = 22050; buf.PlayLength = 0; buf.LoopBegin = 0; buf.LoopLength = 0; buf.LoopCount = 1; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); played = play_to_completion(src, -1); ok(played - running_total == 22050 + 44100, "Got wrong samples played: %u\n", played - running_total); running_total = played; ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends); /* play short segment from middle, loop to the beginning, and end at PlayEnd */ buf.PlayBegin = 22050; buf.PlayLength = 4410; buf.LoopBegin = 0; buf.LoopLength = 0; buf.LoopCount = 1; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); played = play_to_completion(src, -1); ok(played - running_total == 4410 + (22050 + 4410), "Got wrong samples played: %u\n", played - running_total); running_total = played; ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends); /* invalid: LoopEnd must be <= PlayEnd * xaudio27: play until LoopEnd, loop to beginning, play until PlayEnd */ buf.PlayBegin = 22050; buf.PlayLength = 4410; buf.LoopBegin = 0; buf.LoopLength = 22050 + 4410 * 2; buf.LoopCount = 1; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); if(xaudio27){ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); played = play_to_completion(src, -1); ok(played - running_total == 4410 + (22050 + 4410 * 2), "Got wrong samples played: %u\n", played - running_total); running_total = played; ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends); }else ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr); /* invalid: LoopEnd must be within play range * xaudio27: plays only play range */ buf.PlayBegin = 22050; buf.PlayLength = 0; /* == until end of buffer */ buf.LoopBegin = 0; buf.LoopLength = 22050; buf.LoopCount = 1; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); if(xaudio27){ ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); played = play_to_completion(src, -1); ok(played - running_total == 22050, "Got wrong samples played: %u\n", played - running_total); running_total = played; ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends); }else ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr); /* invalid: LoopBegin must be before PlayEnd * xaudio27: crashes */ if(!xaudio27){ buf.PlayBegin = 0; buf.PlayLength = 4410; buf.LoopBegin = 22050; buf.LoopLength = 4410; buf.LoopCount = 1; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr); } /* infinite looping buffer */ buf.PlayBegin = 22050; buf.PlayLength = 0; buf.LoopBegin = 0; buf.LoopLength = 0; buf.LoopCount = 255; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); played = play_to_completion(src, running_total + 88200); ok(played - running_total == 22050 + 44100 * 2, "Got wrong samples played: %u\n", played - running_total); ok(nloopends == (played - running_total) / 88200 + 1, "Got wrong OnLoopEnd calls: %u\n", nloopends); running_total = played; if(xaudio27) IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src); else IXAudio2SourceVoice_DestroyVoice(src); IXAudio2MasteringVoice_DestroyVoice(master); HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData); }
static void test_buffer_callbacks(IXAudio2 *xa) { HRESULT hr; IXAudio2MasteringVoice *master; IXAudio2SourceVoice *src; WAVEFORMATEX fmt; XAUDIO2_BUFFER buf; XAUDIO2_VOICE_STATE state; struct vcb_buf_testdata testdata[5]; int i, timeout; obs_calls = 0; obe_calls = 0; XA2CALL_0V(StopEngine); if(xaudio27) hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL); else hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects); ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr); /* test OnBufferStart/End callbacks */ fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; fmt.nChannels = 2; fmt.nSamplesPerSec = 44100; fmt.wBitsPerSample = 32; fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; fmt.cbSize = 0; XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &vcb_buf, NULL, NULL); ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr); memset(&buf, 0, sizeof(buf)); buf.AudioBytes = 4410 * fmt.nBlockAlign; buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes); fill_buf((float*)buf.pAudioData, &fmt, 440, 4410); /* submit same buffer fragment 5 times */ for(i = 0; i < 5; ++i){ testdata[i].idx = i; testdata[i].src = src; buf.pContext = &testdata[i]; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); } hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW); ok(hr == S_OK, "Start failed: %08x\n", hr); XA2CALL_0(StartEngine); ok(hr == S_OK, "StartEngine failed: %08x\n", hr); if(xaudio27){ hr = IXAudio27SourceVoice_SetSourceSampleRate((IXAudio27SourceVoice*)src, 48000); todo_wine ok(hr == S_OK, "SetSourceSampleRate failed: %08x\n", hr); }else{ hr = IXAudio2SourceVoice_SetSourceSampleRate(src, 48000); ok(hr == XAUDIO2_E_INVALID_CALL, "SetSourceSampleRate should have failed: %08x\n", hr); } while(1){ if(xaudio27) IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state); else IXAudio2SourceVoice_GetState(src, &state, 0); if(state.SamplesPlayed >= 4410 * 5) break; Sleep(100); } ok(state.SamplesPlayed == 4410 * 5, "Got wrong samples played\n"); if(xaudio27) IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src); else IXAudio2SourceVoice_DestroyVoice(src); /* test OnStreamEnd callback */ XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &loop_buf, NULL, NULL); ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr); buf.Flags = XAUDIO2_END_OF_STREAM; hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL); ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr); hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW); ok(hr == S_OK, "Start failed: %08x\n", hr); timeout = 0; while(nstreamends == 0 && timeout < 1000){ Sleep(100); timeout += 100; } ok(nstreamends == 1, "Got wrong number of OnStreamEnd calls: %u\n", nstreamends); /* xaudio resets SamplesPlayed after processing an end-of-stream buffer */ if(xaudio27) IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state); else IXAudio2SourceVoice_GetState(src, &state, 0); ok(state.SamplesPlayed == 0, "Got wrong samples played\n"); if(xaudio27) IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src); else IXAudio2SourceVoice_DestroyVoice(src); IXAudio2MasteringVoice_DestroyVoice(master); HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData); }