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);

Reply via email to