Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package FAudio for openSUSE:Factory checked in at 2026-10-18 19:26:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/FAudio (Old) and /work/SRC/openSUSE:Factory/.FAudio.new.3698736 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "FAudio" Sun Oct 18 19:26:42 2026 rev:36 rq:1385980 version:26.10 Changes: -------- --- /work/SRC/openSUSE:Factory/FAudio/FAudio.changes 2026-08-11 17:17:53.787980256 +0200 +++ /work/SRC/openSUSE:Factory/.FAudio.new.3698736/FAudio.changes 2026-10-18 19:27:19.435800135 +0200 @@ -1,0 +2,17 @@ +Sat Oct 17 17:00:33 UTC 2026 - Martin Pluskal <[email protected]> + +- Update to release 26.10: + * FACT: initial support for XACT 3.0 wave event variations + * F3DAudio: float accuracy fixes (FLT_EPSILON, DopplerFactor + edge cases) + * Fix resample taps exceeding the total resample count, which + crashed small buffer updates + * Fix possible race when destroying voices with custom sends + and a possible divide-by-zero for WMA voices + * FACT: relaxed requirements for streaming WaveBank content + * Static struct alignment fix for Apple's linker +- Changes in 26.09: + * FACT: fix Cue replacement search for per-Cue instance limits + * Wine/Win32: create the WMA decoder without using COM + +------------------------------------------------------------------- Old: ---- FAudio-26.08.tar.gz New: ---- FAudio-26.10.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ FAudio.spec ++++++ --- /var/tmp/diff_new_pack.MzUMBm/_old 2026-10-18 19:27:20.032825150 +0200 +++ /var/tmp/diff_new_pack.MzUMBm/_new 2026-10-18 19:27:20.034825234 +0200 @@ -18,7 +18,7 @@ %define sover 0 Name: FAudio -Version: 26.08 +Version: 26.10 Release: 0 Summary: Accuracy-focused XAudio reimplementation License: Zlib ++++++ FAudio-26.08.tar.gz -> FAudio-26.10.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/CMakeLists.txt new/FAudio-26.10/CMakeLists.txt --- old/FAudio-26.08/CMakeLists.txt 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/CMakeLists.txt 2026-10-01 15:01:47.000000000 +0200 @@ -38,7 +38,7 @@ # Version SET(LIB_MAJOR_VERSION "0") SET(LIB_MINOR_VERSION "26") -SET(LIB_REVISION "08") +SET(LIB_REVISION "10") SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}") # Build Type diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/csharp/FAudio.cs new/FAudio-26.10/csharp/FAudio.cs --- old/FAudio-26.08/csharp/FAudio.cs 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/csharp/FAudio.cs 2026-10-01 15:01:47.000000000 +0200 @@ -79,7 +79,7 @@ public const uint FAUDIO_ABI_VERSION = 0; public const uint FAUDIO_MAJOR_VERSION = 26; - public const uint FAUDIO_MINOR_VERSION = 8; + public const uint FAUDIO_MINOR_VERSION = 10; public const uint FAUDIO_PATCH_VERSION = 0; public const uint FAUDIO_COMPILED_VERSION = ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/include/FAudio.h new/FAudio-26.10/include/FAudio.h --- old/FAudio-26.08/include/FAudio.h 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/include/FAudio.h 2026-10-01 15:01:47.000000000 +0200 @@ -496,7 +496,7 @@ #define FAUDIO_ABI_VERSION 0 #define FAUDIO_MAJOR_VERSION 26 -#define FAUDIO_MINOR_VERSION 8 +#define FAUDIO_MINOR_VERSION 10 #define FAUDIO_PATCH_VERSION 0 #define FAUDIO_COMPILED_VERSION ( \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/src/F3DAudio.c new/FAudio-26.10/src/F3DAudio.c --- old/FAudio-26.08/src/F3DAudio.c 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/src/F3DAudio.c 2026-10-01 15:01:47.000000000 +0200 @@ -27,13 +27,7 @@ #include "F3DAudio.h" #include "FAudio_internal.h" -#include <math.h> /* ONLY USE THIS FOR isnan! */ -#include <float.h> /* ONLY USE THIS FOR FLT_MIN/FLT_MAX! */ - -/* VS2010 doesn't define isnan (which is C99), so here it is. */ -#if defined(_MSC_VER) && !defined(isnan) -#define isnan(x) _isnan(x) -#endif +#include <float.h> /* ONLY USE THIS FOR FLT_MIN/FLT_MAX/FLT_EPSILON! */ /* UTILITY MACROS */ @@ -1375,6 +1369,7 @@ */ static inline void CalculateDoppler( float SpeedOfSound, + float SpeedOfSoundEpsilon, const F3DAUDIO_LISTENER* pListener, const F3DAUDIO_EMITTER* pEmitter, F3DAUDIO_VECTOR emitterToListener, @@ -1383,55 +1378,42 @@ float* emitterVelocityComponent, float* DopplerFactor ) { - float scaledSpeedOfSound; *DopplerFactor = 1.0f; /* Project... */ - if (eToLDistance != 0.0f) + if (eToLDistance > FLT_EPSILON) { *listenerVelocityComponent = VectorDot(emitterToListener, pListener->Velocity) / eToLDistance; *emitterVelocityComponent = VectorDot(emitterToListener, pEmitter->Velocity) / eToLDistance; + + if (pEmitter->DopplerScaler > 0.0f) + { + /* Multiply... */ + float scaledListenerVelocityComponent = *listenerVelocityComponent * pEmitter->DopplerScaler; + float scaledEmitterVelocityComponent = *emitterVelocityComponent * pEmitter->DopplerScaler; + + /* ... then Clamp. */ + *DopplerFactor = ( + SpeedOfSound - FAudio_clamp(scaledListenerVelocityComponent, -SpeedOfSoundEpsilon, SpeedOfSoundEpsilon) + ) / ( + SpeedOfSound - FAudio_clamp(scaledEmitterVelocityComponent, -SpeedOfSoundEpsilon, SpeedOfSoundEpsilon) + ); + + /* Limit the pitch shifting to 2 octaves up and 1 octave down */ + *DopplerFactor = FAudio_clamp( + *DopplerFactor, + 0.5f, + 4.0f + ); + } } else { *listenerVelocityComponent = 0.0f; *emitterVelocityComponent = 0.0f; } - - if (pEmitter->DopplerScaler > 0.0f) - { - scaledSpeedOfSound = SpeedOfSound / pEmitter->DopplerScaler; - - /* Clamp... */ - *listenerVelocityComponent = FAudio_min( - *listenerVelocityComponent, - scaledSpeedOfSound - ); - *emitterVelocityComponent = FAudio_min( - *emitterVelocityComponent, - scaledSpeedOfSound - ); - - /* ... then Multiply. */ - *DopplerFactor = ( - SpeedOfSound - pEmitter->DopplerScaler * *listenerVelocityComponent - ) / ( - SpeedOfSound - pEmitter->DopplerScaler * *emitterVelocityComponent - ); - if (isnan(*DopplerFactor)) /* If emitter/listener are at the same pos... */ - { - *DopplerFactor = 1.0f; - } - - /* Limit the pitch shifting to 2 octaves up and 1 octave down */ - *DopplerFactor = FAudio_clamp( - *DopplerFactor, - 0.5f, - 4.0f - ); - } } void F3DAudioCalculate( @@ -1445,13 +1427,19 @@ F3DAUDIO_VECTOR emitterToListener; float eToLDistance, normalizedDistance, dp; + /* Clang treats #pragma pack(push, 1) as both pack and align attributes. + * 1 byte alignment can produce UB or even errors with modern Apple linker: + * https://github.com/FNA-XNA/FAudio/issues/362 + * - F3DAUDIO_DISTANCE_CURVE_POINT requires 4 bytes alignment for float values + * - F3DAUDIO_DISTANCE_CURVE requires 8 bytes alignment for 64-bit pointer + */ #define DEFAULT_POINTS(name, x1, y1, x2, y2) \ - static F3DAUDIO_DISTANCE_CURVE_POINT name##Points[2] = \ + static ALIGN(F3DAUDIO_DISTANCE_CURVE_POINT, 4) name##Points[2] = \ { \ { x1, y1 }, \ { x2, y2 } \ }; \ - static F3DAUDIO_DISTANCE_CURVE name##Default = \ + static ALIGN(F3DAUDIO_DISTANCE_CURVE, 8) name##Default = \ { \ (F3DAUDIO_DISTANCE_CURVE_POINT*) &name##Points[0], 2 \ }; @@ -1521,6 +1509,7 @@ { CalculateDoppler( SPEEDOFSOUND(Instance), + SPEEDOFSOUNDEPSILON(Instance), pListener, pEmitter, emitterToListener, @@ -1537,8 +1526,7 @@ /* Determined roughly. * Below that distance, the emitter angle is considered to be PI/2. */ - #define EMITTER_ANGLE_NULL_DISTANCE 1.2e-7 - if (eToLDistance < EMITTER_ANGLE_NULL_DISTANCE) + if (eToLDistance < FLT_EPSILON) { pDSPSettings->EmitterToListenerAngle = F3DAUDIO_PI / 2.0f; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/src/FACT3D.c new/FAudio-26.10/src/FACT3D.c --- old/FAudio-26.08/src/FACT3D.c 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/src/FACT3D.c 2026-10-01 15:01:47.000000000 +0200 @@ -25,6 +25,7 @@ */ #include "FACT3D.h" +#include "FAudio_internal.h" uint32_t FACT3DInitialize( FACTAudioEngine *pEngine, @@ -64,12 +65,18 @@ F3DAUDIO_EMITTER *pEmitter, F3DAUDIO_DSP_SETTINGS *pDSPSettings ) { - static F3DAUDIO_DISTANCE_CURVE_POINT DefaultCurvePoints[2] = + /* Clang treats #pragma pack(push, 1) as both pack and align attributes. + * 1 byte alignment can produce UB or even errors with modern Apple linker: + * https://github.com/FNA-XNA/FAudio/issues/362 + * - F3DAUDIO_DISTANCE_CURVE_POINT requires 4 bytes alignment for float values + * - F3DAUDIO_DISTANCE_CURVE requires 8 bytes alignment for 64-bit pointer + */ + static ALIGN(F3DAUDIO_DISTANCE_CURVE_POINT, 4) DefaultCurvePoints[2] = { { 0.0f, 1.0f }, { 1.0f, 1.0f } }; - static F3DAUDIO_DISTANCE_CURVE DefaultCurve = + static ALIGN(F3DAUDIO_DISTANCE_CURVE, 8) DefaultCurve = { (F3DAUDIO_DISTANCE_CURVE_POINT*) &DefaultCurvePoints[0], 2 }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/src/FACT_internal.c new/FAudio-26.10/src/FACT_internal.c --- old/FAudio-26.08/src/FACT_internal.c 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/src/FACT_internal.c 2026-10-01 15:01:47.000000000 +0200 @@ -549,8 +549,20 @@ if (cursor == cue || !cursor->playingSound || (cursor->state & (FACT_STATE_STOPPING | FACT_STATE_STOPPED))) continue; - if (category && category != &engine->categories[cursor->playingSound->sound->category]) - continue; + if (category) + { + if (category != &engine->categories[cursor->playingSound->sound->category]) + { + continue; + } + } + else + { + if (cursor->index != cue->index) + { + continue; + } + } /* FIXME: How does QUEUE differ from REPLACE_OLDEST? */ if (behaviour == MAX_INSTANCE_BEHAVIOR_QUEUE @@ -2245,12 +2257,32 @@ return FAUDIO_OK; } -void FACT_INTERNAL_ParseTrackEvents( - const uint8_t **ptr, - bool se, - FACTTrack *track, - FAudioMallocFunc pMalloc -) { +static uint16_t variation_flags_from_3_0(uint8_t old_flags) +{ + uint16_t flags = 0; + + if (old_flags & 0x01) + flags |= VARIATION_FLAG_VOLUME_ADD; + if (old_flags & 0x02) + FAudio_Log("Ignoring unknown 3.0 variation flag 0x2.\n"); + if (old_flags & 0x04) + flags |= VARIATION_FLAG_PITCH_ADD; + if (old_flags & 0x08) + FAudio_Log("Ignoring unknown 3.0 variation flag 0x8.\n"); + if (old_flags & 0x10) + flags |= VARIATION_FLAG_PITCH_NEW_ON_LOOP; + if (old_flags & 0x20) + flags |= VARIATION_FLAG_VOLUME_NEW_ON_LOOP; + if (old_flags & 0x40) + flags |= VARIATION_FLAG_PITCH; + if (old_flags & 0x80) + flags |= VARIATION_FLAG_VOLUME; + return flags; +} + +static void parse_track_events(const uint8_t **ptr, bool se, FACTTrack *track, + FAudioMallocFunc pMalloc, uint16_t content_version) +{ FACTEvent *events; uint32_t evtInfo; uint8_t minWeight, maxWeight, separator; @@ -2338,11 +2370,18 @@ event->wave.maxPitch = read_s16(ptr, se); event->wave.minVolume = read_volbyte(ptr); event->wave.maxVolume = read_volbyte(ptr); - event->wave.minFrequency = read_f32(ptr, se); - event->wave.maxFrequency = read_f32(ptr, se); - event->wave.minQFactor = read_f32(ptr, se); - event->wave.maxQFactor = read_f32(ptr, se); - event->wave.variationFlags = read_u16(ptr, se); + if (content_version > FACT_CONTENT_VERSION_3_0) + { + event->wave.minFrequency = read_f32(ptr, se); + event->wave.maxFrequency = read_f32(ptr, se); + event->wave.minQFactor = read_f32(ptr, se); + event->wave.maxQFactor = read_f32(ptr, se); + event->wave.variationFlags = read_u16(ptr, se); + } + else + { + event->wave.variationFlags = variation_flags_from_3_0(read_u8(ptr)); + } } else if (EVTTYPE(FACTEVENT_PLAYWAVETRACKEFFECTVARIATION)) { @@ -2360,11 +2399,18 @@ event->wave.maxPitch = read_s16(ptr, se); event->wave.minVolume = read_volbyte(ptr); event->wave.maxVolume = read_volbyte(ptr); - event->wave.minFrequency = read_f32(ptr, se); - event->wave.maxFrequency = read_f32(ptr, se); - event->wave.minQFactor = read_f32(ptr, se); - event->wave.maxQFactor = read_f32(ptr, se); - event->wave.variationFlags = read_u16(ptr, se); + if (content_version > FACT_CONTENT_VERSION_3_0) + { + event->wave.minFrequency = read_f32(ptr, se); + event->wave.maxFrequency = read_f32(ptr, se); + event->wave.minQFactor = read_f32(ptr, se); + event->wave.maxQFactor = read_f32(ptr, se); + event->wave.variationFlags = read_u16(ptr, se); + } + else + { + event->wave.variationFlags = variation_flags_from_3_0(read_u8(ptr)); + } /* Track Variation */ evtInfo = read_u32(ptr, se); @@ -2702,7 +2748,7 @@ FACTTrack *track = &tracks[j]; ptr = start + track->code; - FACT_INTERNAL_ParseTrackEvents(&ptr, se, track, pEngine->pMalloc); + parse_track_events(&ptr, se, track, pEngine->pMalloc, contentVersion); } } } @@ -3057,9 +3103,22 @@ /* Native forbids creating an in-memory wave bank when the flags * include STREAMING. It allows creating a streaming wave bank * when the flags do not include STREAMING, but subsequent - * attempts to use the wave bank crash. Forbid both. */ - pEngine->pFree(wb); - return FACTENGINE_E_INVALIDUSAGE; + * attempts to use the wave bank crash. + * + * We _should_ forbid both, but for whatever reason XAudio2 + * thought it could handle this case. Fortunately, FAudio _does_ + * handle this without crashing, so leave it a bit broken here. + */ + if (wb->streaming) + { + pEngine->pFree(wb); + return FACTENGINE_E_INVALIDUSAGE; + } + else + { + /* Per the above, just pretend we're streaming in this case */ + wb->streaming = isStreaming; + } } wb->entryCount = wbinfo.dwEntryCount; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/src/FAudio.c new/FAudio-26.10/src/FAudio.c --- old/FAudio-26.08/src/FAudio.c 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/src/FAudio.c 2026-10-01 15:01:47.000000000 +0200 @@ -545,10 +545,11 @@ else if (COMPARE_GUID(IEEE_FLOAT)) { /* FIXME: Weird behavior! - * Prototype creates a source with the IEEE_FLOAT tag, - * but it's actually PCM16. It seems to prioritize - * wBitsPerSample over the format tag. Not sure if we - * should fold this section into the section above...? + * Prototype (appid 10150) creates a source with the + * IEEE_FLOAT tag, but it's actually PCM16. It seems to + * prioritize wBitsPerSample over the format tag. Not + * sure if we should fold this section into the section + * above...? * -flibit */ if (fmtex->Format.wBitsPerSample == 16) @@ -2430,12 +2431,16 @@ while (list != NULL) { source = (FAudioSourceVoice*) list->entry; + FAudio_PlatformLockMutex(source->sendLock); + LOG_MUTEX_LOCK(audio, source->sendLock) for (i = 0; i < source->sends.SendCount; i += 1) if (source->sends.pSends[i].pOutputVoice == voice) { ret = 0x80004005; /* E_FAIL */ break; } + FAudio_PlatformUnlockMutex(source->sendLock); + LOG_MUTEX_UNLOCK(audio, source->sendLock) if (ret) break; list = list->next; @@ -2450,12 +2455,16 @@ while (list != NULL) { submix = (FAudioSubmixVoice*) list->entry; + FAudio_PlatformLockMutex(submix->sendLock); + LOG_MUTEX_LOCK(audio, submix->sendLock) for (i = 0; i < submix->sends.SendCount; i += 1) if (submix->sends.pSends[i].pOutputVoice == voice) { ret = 0x80004005; /* E_FAIL */ break; } + FAudio_PlatformUnlockMutex(submix->sendLock); + LOG_MUTEX_UNLOCK(audio, submix->sendLock) if (ret) break; list = list->next; @@ -2496,8 +2505,14 @@ FAudio_PlatformUnlockMutex(voice->audio->sourceLock); LOG_MUTEX_UNLOCK(voice->audio, voice->audio->sourceLock) - voice->audio->pFree(voice->src.queued_buffers); - voice->audio->pFree(voice->src.flush_buffers); + if (voice->src.queued_buffers != NULL) + { + voice->audio->pFree(voice->src.queued_buffers); + } + if (voice->src.flush_buffers != NULL) + { + voice->audio->pFree(voice->src.flush_buffers); + } voice->audio->pFree(voice->src.format); LOG_MUTEX_DESTROY(voice->audio, voice->src.bufferLock) FAudio_PlatformDestroyMutex(voice->src.bufferLock); @@ -2507,7 +2522,10 @@ FAudio_WMADEC_free(voice); } #endif /* HAVE_WMADEC */ - voice->audio->pFree(voice->src.unaligned_data); + if (voice->src.unaligned_data != NULL) + { + voice->audio->pFree(voice->src.unaligned_data); + } } else if (voice->type == FAUDIO_VOICE_SUBMIX) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/src/FAudio_internal.c new/FAudio-26.10/src/FAudio_internal.c --- old/FAudio-26.08/src/FAudio_internal.c 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/src/FAudio_internal.c 2026-10-01 15:01:47.000000000 +0200 @@ -328,7 +328,7 @@ ) { const uint32_t block_size = voice->src.format->nBlockAlign; const uint32_t samples_per_block = voice->src.samples_per_block; - uint32_t result = (decoding * block_size / samples_per_block); + uint32_t result; FAudioWaveFormatExtensible *fmt; LOG_FUNC_ENTER(voice->audio) @@ -342,6 +342,7 @@ } #endif /* HAVE_WMADEC */ + result = (decoding * block_size / samples_per_block); for (size_t i = 0; i < voice->src.queued_buffer_count; ++i) { const struct queued_buffer *buffer = &voice->src.queued_buffers[i]; @@ -1147,6 +1148,7 @@ { /* Actually, just use the existing buffer... */ finalSamples = voice->audio->decoded_audio; + voice->src.resampleOffset += (toResample << FIXED_PRECISION); } else { @@ -1175,30 +1177,44 @@ *dst++ = lerp(voice->src.resample_taps[0][i], voice->src.resample_taps[1][i], frac); voice->src.resampleOffset += voice->src.resampleStep; - ++tap_samples; + + if (++tap_samples >= toResample) + { + break; + } } /* Then the samples between the last sample of the * previous quantum and the first sample of this one. */ - while ((voice->src.resampleOffset >> FIXED_PRECISION) < prev_sample_count) + if (tap_samples < toResample) { - float frac = fixed_to_float(voice->src.resampleOffset & FIXED_FRACTION_MASK); + while ((voice->src.resampleOffset >> FIXED_PRECISION) < prev_sample_count) + { + float frac = fixed_to_float(voice->src.resampleOffset & FIXED_FRACTION_MASK); - for (unsigned int i = 0; i < channels; ++i) - *dst++ = lerp(voice->src.resample_taps[1][i], voice->audio->decoded_audio[i], frac); + for (unsigned int i = 0; i < channels; ++i) + *dst++ = lerp(voice->src.resample_taps[1][i], voice->audio->decoded_audio[i], frac); - voice->src.resampleOffset += voice->src.resampleStep; - ++tap_samples; + voice->src.resampleOffset += voice->src.resampleStep; + + if (++tap_samples >= toResample) + { + break; + } + } } - voice->src.resample( - voice->audio->decoded_audio, - dst, - &voice->src.resampleOffset, - voice->src.resampleStep, - toResample - tap_samples, - channels - ); + if (tap_samples < toResample) + { + voice->src.resample( + voice->audio->decoded_audio, + dst, + &voice->src.resampleOffset, + voice->src.resampleStep, + toResample - tap_samples, + channels + ); + } finalSamples = voice->audio->resampled_audio; /* Actually this is probably wrong in the case we do get a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/FAudio-26.08/src/FAudio_platform_win32_wmadec.c new/FAudio-26.10/src/FAudio_platform_win32_wmadec.c --- old/FAudio-26.08/src/FAudio_platform_win32_wmadec.c 2026-08-01 17:26:07.000000000 +0200 +++ new/FAudio-26.10/src/FAudio_platform_win32_wmadec.c 2026-10-01 15:01:47.000000000 +0200 @@ -247,6 +247,34 @@ LOG_FUNC_EXIT(voice->audio) } +static HRESULT create_wma_decoder(IMFTransform **out) +{ + static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID, REFIID, void **); + IClassFactory *factory; + HMODULE wmadmod; + HRESULT hr; + + if (!pDllGetClassObject) + { + if (!(wmadmod = LoadLibraryW(L"wmadmod.dll"))) + return E_FAIL; + + pDllGetClassObject = (HRESULT (WINAPI *)(REFCLSID, REFIID, void **)) GetProcAddress(wmadmod, "DllGetClassObject"); + + if (!pDllGetClassObject) + return E_FAIL; + } + + hr = pDllGetClassObject(&CLSID_CWMADecMediaObject, &IID_IClassFactory, (void **)&factory); + if (FAILED(hr)) + return hr; + + hr = IClassFactory_CreateInstance(factory, NULL, &IID_IMFTransform, (void **)out); + IClassFactory_Release(factory); + + return hr; +} + uint32_t FAudio_WMADEC_init(FAudioSourceVoice *voice, uint32_t type) { static const uint8_t fake_codec_data[16] = {0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -266,13 +294,7 @@ if (!(impl = voice->audio->pMalloc(sizeof(*impl)))) return -1; FAudio_memset(impl, 0, sizeof(*impl)); - hr = CoCreateInstance( - &CLSID_CWMADecMediaObject, - 0, - CLSCTX_INPROC_SERVER, - &IID_IMFTransform, - (void **)&decoder - ); + hr = create_wma_decoder(&decoder); if (FAILED(hr)) { voice->audio->pFree(impl->output_buf);
