HRESULT CDECL CreateFX(REFCLSID clsid, IUnknown **out, void *initdata, UINT32 initdata_bytes) { HRESULT hr; IUnknown *obj; const GUID *class; *out = NULL; class = clsid; if(IsEqualGUID(clsid, &CLSID_FXReverb27) || IsEqualGUID(clsid, &CLSID_FXReverb)) class = &CLSID_WINE_FXReverb28; hr = CoCreateInstance(class, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&obj); if(FAILED(hr)){ WARN("CoCreateInstance failed: %08x\n", hr); return hr; } if(initdata && initdata_bytes > 0){ IXAPO *xapo; hr = IUnknown_QueryInterface(obj, &IID_IXAPO, (void**)&xapo); if(SUCCEEDED(hr)){ hr = IXAPO_Initialize(xapo, initdata, initdata_bytes); IXAPO_Release(xapo); if(FAILED(hr)){ WARN("Initialize failed: %08x\n", hr); IUnknown_Release(obj); return hr; } } } *out = obj; return S_OK; }
static void test_xapo_creation_legacy(const char *module, unsigned int version) { HANDLE xapofxdll; HRESULT hr; IUnknown *fx_unk; unsigned int i; HRESULT (CDECL *pCreateFX)(REFCLSID,IUnknown**) = NULL; /* CLSIDs are the same across all versions */ static struct { const GUID *clsid; BOOL todo; } const_clsids[] = { { &CLSID_FXEQ27, FALSE }, { &CLSID_FXMasteringLimiter27, TRUE }, { &CLSID_FXReverb27, FALSE }, { &CLSID_FXEcho27, TRUE}, /* older versions of xapofx actually have support for new clsids */ { &CLSID_FXEQ, FALSE }, { &CLSID_FXMasteringLimiter, TRUE }, { &CLSID_FXReverb, FALSE }, { &CLSID_FXEcho, TRUE} }; /* different CLSID for each version */ static const GUID *avm_clsids[] = { &CLSID_AudioVolumeMeter20, &CLSID_AudioVolumeMeter21, &CLSID_AudioVolumeMeter22, &CLSID_AudioVolumeMeter23, &CLSID_AudioVolumeMeter24, &CLSID_AudioVolumeMeter25, &CLSID_AudioVolumeMeter26, &CLSID_AudioVolumeMeter27 }; static const GUID *ar_clsids[] = { &CLSID_AudioReverb20, &CLSID_AudioReverb21, &CLSID_AudioReverb22, &CLSID_AudioReverb23, &CLSID_AudioReverb24, &CLSID_AudioReverb25, &CLSID_AudioReverb26, &CLSID_AudioReverb27 }; xapofxdll = LoadLibraryA(module); if(xapofxdll){ pCreateFX = (void*)GetProcAddress(xapofxdll, "CreateFX"); ok(pCreateFX != NULL, "%s did not have CreateFX?\n", module); if(!pCreateFX){ FreeLibrary(xapofxdll); return; } }else{ win_skip("Couldn't load %s\n", module); return; } if(pCreateFX){ for(i = 0; i < sizeof(const_clsids) / sizeof(*const_clsids); ++i){ hr = pCreateFX(const_clsids[i].clsid, &fx_unk); if(const_clsids[i].todo) todo_wine ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(const_clsids[i].clsid), hr); else ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(const_clsids[i].clsid), hr); if(SUCCEEDED(hr)){ IXAPO *xapo; hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO27, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO27 interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); IUnknown_Release(fx_unk); } hr = CoCreateInstance(const_clsids[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&fx_unk); ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance should have failed: %08x\n", hr); if(SUCCEEDED(hr)) IUnknown_Release(fx_unk); } hr = pCreateFX(avm_clsids[version - 20], &fx_unk); ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(avm_clsids[version - 20]), hr); if(SUCCEEDED(hr)){ IXAPO *xapo; hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO27, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO27 interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); IUnknown_Release(fx_unk); } hr = pCreateFX(ar_clsids[version - 20], &fx_unk); ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(ar_clsids[version - 20]), hr); if(SUCCEEDED(hr)){ IXAPO *xapo; hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO27, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO27 interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); IUnknown_Release(fx_unk); } } FreeLibrary(xapofxdll); }
static void test_xapo_creation_modern(const char *module) { HANDLE xaudio2dll; HRESULT hr; IUnknown *fx_unk; unsigned int i; HRESULT (CDECL *pCreateFX)(REFCLSID,IUnknown**,void*,UINT32) = NULL; HRESULT (WINAPI *pCAVM)(IUnknown**) = NULL; HRESULT (WINAPI *pCAR)(IUnknown**) = NULL; /* CLSIDs are the same across all versions */ static struct { const GUID *clsid; BOOL todo; } const_clsids[] = { { &CLSID_FXEQ27, FALSE }, { &CLSID_FXMasteringLimiter27, TRUE }, { &CLSID_FXReverb27, FALSE }, { &CLSID_FXEcho27, TRUE}, { &CLSID_FXEQ, FALSE }, { &CLSID_FXMasteringLimiter, TRUE }, { &CLSID_FXReverb, FALSE }, { &CLSID_FXEcho, TRUE} }; xaudio2dll = LoadLibraryA(module); if(xaudio2dll){ pCreateFX = (void*)GetProcAddress(xaudio2dll, "CreateFX"); ok(pCreateFX != NULL, "%s did not have CreateFX?\n", module); if(!pCreateFX){ FreeLibrary(xaudio2dll); return; } }else{ win_skip("Couldn't load %s\n", module); return; } if(pCreateFX){ for(i = 0; i < sizeof(const_clsids) / sizeof(*const_clsids); ++i){ hr = pCreateFX(const_clsids[i].clsid, &fx_unk, NULL, 0); if(const_clsids[i].todo) todo_wine ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(const_clsids[i].clsid), hr); else ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(const_clsids[i].clsid), hr); if(SUCCEEDED(hr)){ IXAPO *xapo; hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); IUnknown_Release(fx_unk); } hr = CoCreateInstance(const_clsids[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&fx_unk); ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance should have failed: %08x\n", hr); if(SUCCEEDED(hr)) IUnknown_Release(fx_unk); } /* test legacy CLSID */ hr = pCreateFX(&CLSID_AudioVolumeMeter27, &fx_unk, NULL, 0); ok(hr == S_OK, "%s: CreateFX(CLSID_AudioVolumeMeter) failed: %08x\n", module, hr); if(SUCCEEDED(hr)){ IXAPO *xapo; hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); IUnknown_Release(fx_unk); } } pCAVM = (void*)GetProcAddress(xaudio2dll, "CreateAudioVolumeMeter"); ok(pCAVM != NULL, "%s did not have CreateAudioVolumeMeter?\n", module); hr = pCAVM(&fx_unk); ok(hr == S_OK, "CreateAudioVolumeMeter failed: %08x\n", hr); if(SUCCEEDED(hr)){ IXAPO *xapo; hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); IUnknown_Release(fx_unk); } pCAR = (void*)GetProcAddress(xaudio2dll, "CreateAudioReverb"); ok(pCAR != NULL, "%s did not have CreateAudioReverb?\n", module); hr = pCAR(&fx_unk); ok(hr == S_OK, "CreateAudioReverb failed: %08x\n", hr); if(SUCCEEDED(hr)){ IXAPO *xapo; hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); IUnknown_Release(fx_unk); } FreeLibrary(xaudio2dll); }
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; DWORD chmask; 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); if(!xaudio27){ chmask = 0xdeadbeef; IXAudio2MasteringVoice_GetChannelMask(master, &chmask); ok(chmask == (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT), "Got unexpected channel mask: 0x%x\n", chmask); } /* 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){ IXAPO *xapo; hr = CoCreateInstance(&CLSID_AudioVolumeMeter27, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&vumeter); ok(hr == S_OK, "CoCreateInstance(AudioVolumeMeter) failed: %08x\n", hr); hr = IUnknown_QueryInterface(vumeter, &IID_IXAPO27, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO27 interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); }else{ IXAPO *xapo; hr = pCreateAudioVolumeMeter(&vumeter); ok(hr == S_OK, "CreateAudioVolumeMeter failed: %08x\n", hr); hr = IUnknown_QueryInterface(vumeter, &IID_IXAPO, (void**)&xapo); ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr); if(SUCCEEDED(hr)) IXAPO_Release(xapo); } 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); }