static UINT32 play_to_completion(IXAudio2SourceVoice *src, UINT32 max_samples) { XAUDIO2_VOICE_STATE state; HRESULT hr; nloopends = 0; hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW); ok(hr == S_OK, "Start failed: %08x\n", hr); while(1){ if(xaudio27) IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state); else IXAudio2SourceVoice_GetState(src, &state, 0); if(state.BuffersQueued == 0) break; if(state.SamplesPlayed >= max_samples){ if(xaudio27) IXAudio27SourceVoice_ExitLoop((IXAudio27SourceVoice*)src, XAUDIO2_COMMIT_NOW); else IXAudio2SourceVoice_ExitLoop(src, XAUDIO2_COMMIT_NOW); } Sleep(100); } hr = IXAudio2SourceVoice_Stop(src, 0, XAUDIO2_COMMIT_NOW); ok(hr == S_OK, "Start failed: %08x\n", hr); return state.SamplesPlayed; }
static void WINAPI vcb_buf_OnBufferStart(IXAudio2VoiceCallback *This, void *pBufferContext) { struct vcb_buf_testdata *data = pBufferContext; XAUDIO2_VOICE_STATE state; ok(data->idx == obs_calls, "Buffer callback out of order: %u\n", data->idx); if(xaudio27) IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)data->src, &state); else IXAudio2SourceVoice_GetState(data->src, &state, 0); ok(state.BuffersQueued == 5 - obs_calls, "Got wrong number of buffers remaining: %u\n", state.BuffersQueued); ok(state.pCurrentBufferContext == pBufferContext, "Got wrong buffer from GetState\n"); ++obs_calls; }
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 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); }