Skip to content

bugfix(audio): Apply configured volume to Bink movie audio - #3083

Merged
xezon merged 13 commits into
TheSuperHackers:mainfrom
CryoTheRenegade:bugfix/2850-video-audio-volume
Sep 2, 2026
Merged

bugfix(audio): Apply configured volume to Bink movie audio#3083
xezon merged 13 commits into
TheSuperHackers:mainfrom
CryoTheRenegade:bugfix/2850-video-audio-volume

Conversation

@CryoTheRenegade

@CryoTheRenegade CryoTheRenegade commented Aug 9, 2026

Copy link
Copy Markdown

Fixes #2850.

Problem

Bink movie audio bypasses the Miles mixer. The initial BinkSetVolume() call ran before Bink's audio output was ready, so movies ignored the configured Speech volume and could play at full volume.

Changes

  • Call BinkWait() before applying the initial volume in BinkVideoPlayer::createStream().
  • Add VideoPlayerInterface::setVolume() and implement it in BinkVideoPlayer so Speech-volume changes update every open Bink stream.
  • Keep the retail volume conversion, including its nonzero minimum because Bink treats a literal volume of 0 as full volume.
  • Use explicit no-op implementations for FFmpeg and tool-only video players, whose audio volume is not handled by this Bink path.

Testing

  • Built all Win32 Release targets for Generals and Zero Hour with MSVC, including MapCacheBuilder and WorldBuilder.
  • Started Zero Hour through the rebuilt executable and verified Bink intro playback, the Options Voice Volume control, menu flow, and clean exit.
  • Started a Challenge at Speech 0 and Speech 100. The loading interval measured -28.8 dB mean / -12.0 dB peak at Speech 0 and -18.3 dB mean / -0.1 dB peak at Speech 100. The capture also contained unaffected music and sound effects.
  • Replaced EALogoMovie synchronously with Sizzle in a test harness. The replacement rendered normally and received the configured volume. The same 35-second interval measured -83.3 dB mean / -66.2 dB peak at Speech 0 and -19.7 dB mean / -2.5 dB peak at Speech 100.

Fixes TheSuperHackers#2850. Movie audio ignored the Options volume sliders because
BinkSetVolume was called once in createStream(), before Bink's audio
output had started, so it never took effect. Extract the volume calc
into calculateMovieAudioVolume() and reapply it on every decoded frame
in frameDecompress() so it takes effect and tracks live slider changes.
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Fix the floor comment (formula is unchanged from retail, floor is 327
not 1) and drop the live-slider-change claim from the per-frame comment;
the Options menu isn't reachable during movie playback. The reason to
reapply every frame is that the one-shot createStream() call ran before
Bink's audio output started, so it never took effect.
@xezon xezon added Audio Is audio related Bug Something is not working right, typically is user facing Minor Severity: Minor < Major < Critical < Blocker labels Aug 9, 2026
Per review: don't reapply the volume every frame. The original defect
was that BinkSetVolume ran in createStream(), before Bink's audio output
existed, so it was discarded. Apply it once on the first BinkDoFrame(),
the earliest point it can actually take effect. Drops the createStream()
call and the per-frame poll in favor of a one-shot latch.
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Comment thread Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h Outdated
@Skyaero42

Copy link
Copy Markdown

I don't think the title is correct, as the volume is not applied every frame, but only once.

@CryoTheRenegade CryoTheRenegade changed the title bugfix(audio): Reapply Bink movie volume every frame bugfix(audio): Reapply Bink movie volume on first frame Aug 10, 2026
- Return the 327 floor instead of 0 on the null-audio path so it does not
  trip Bink's 'play at full volume' quirk.
- Trim the redundant formula comment.
- Restore retail tab alignment on m_handle/m_memFile and align m_volumeSet.
@CryoTheRenegade

Copy link
Copy Markdown
Author

I don't think the title is correct, as the volume is not applied every frame, but only once.

fixed

Comment thread Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Per xezon's review. Replace the per-frame latch with a push model:

- VideoPlayerInterface gains a setVolume(Real) virtual (no-op default in
  VideoPlayer); BinkVideoPlayer overrides it to push the volume to every
  open stream's Bink audio output.
- MilesAudioManager::processPlayingList() pushes the speech volume to
  TheVideoPlayer whenever the volume changes, so movies that bypass the
  Miles mixer follow the sliders.
- BinkVideoPlayer::update() applies the volume once on the first frame a
  stream exists, fixing the original too-early set in createStream()
  (Bink's audio output is not running yet at creation, so it was lost).
- calculateMovieAudioVolume() now takes the speech volume as a parameter.
Comment thread Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h Outdated
@Skyaero42

Skyaero42 commented Aug 10, 2026

Copy link
Copy Markdown

You are clearly using AI. While there is in principle nothing against it, I would strongly recommend you review the changes it makes - per our contribution guide.
The sloppy improvements currently take up unnecessary and valuable review time.

Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Comment thread Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp
Comment thread Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h Outdated
Comment thread Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Comment thread Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated

virtual void notifyVideoPlayerOfNewProvider( Bool nowHasValid ) override { }

virtual void setVolume( Real volume ) override { }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FFmpegVideoPlayer derives from VideoPlayer, so it picks up this no-op and the volume plumbing is Bink-only. Override it there too?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FFmpegVideoPlayer now overrides setVolume and pushes the speech volume to the OpenAL movie stream. Initial volume is also applied when the stream starts, since that backend is already live by then.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait do we have OpenAL in upstream yet? This might not work until we get that landed :(

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, OpenAL is not in this repo yet. The FFmpeg override is behind RTS_USE_OPENAL so Miles/Bink builds keep a no-op, and the OpenAL gain path is just plumbing until that backend lands.

CryoTheRenegade and others added 2 commits August 21, 2026 08:42
Co-authored-by: Cursor <cursoragent@cursor.com>
@bobtista

Copy link
Copy Markdown

This is looking good :) Can you do some testing and add the results to the PR description? eg

  1. Starting a Challenge/movie with Speech volume already at 0 or a low value.
  2. Replacing one Bink movie with another without an intervening empty update.
  3. Confirming the replacement movie also receives the configured volume.

@CryoTheRenegade

Copy link
Copy Markdown
Author

Done

Comment thread Core/GameEngine/Include/GameClient/VideoPlayer.h Outdated
Comment thread Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
@greptile-apps

greptile-apps Bot commented Aug 30, 2026

Copy link
Copy Markdown

Greptile Summary

The PR updates Bink movie audio to apply the configured speech volume after polling the newly opened stream and propagates subsequent speech-volume changes to active movies.

  • Adds a shared video-player volume-control contract with Bink, FFmpeg, and null-provider implementations.
  • Applies Bink volume after BinkWait during stream creation and updates every open Bink stream when the setting changes.
  • Uses NullVideoPlayer in non-video tool targets so they continue satisfying the expanded interface.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Applies initial volume after polling the Bink stream and propagates later volume changes across open streams.
Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp Forwards changed speech volume to the active video-player provider during audio-list processing.
Core/GameEngine/Include/GameClient/VideoPlayer.h Expands the shared video-player contract with volume control and supplies a no-op null implementation.
Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h Keeps the optional FFmpeg provider compatible with the expanded interface through a no-op override.

Sequence Diagram

sequenceDiagram
    participant Audio as MilesAudioManager
    participant Player as BinkVideoPlayer
    participant Stream as BinkVideoStream
    participant Bink as Bink API
    Player->>Stream: createStream(handle)
    Stream->>Bink: BinkWait(handle)
    Player->>Bink: BinkSetVolume(initial volume)
    Audio->>Player: setVolume(speech volume)
    loop Every open stream
        Player->>Bink: BinkSetVolume(updated volume)
    end
Loading

Reviews (3): Last reviewed commit: "refactor(video): make null players expli..." | Re-trigger Greptile

@xezon xezon left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to see this got rid of the update loop hack.

Comment thread Core/GameEngine/Include/GameClient/VideoPlayer.h Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Comment thread Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp Outdated
Comment thread Core/GameEngine/Include/GameClient/VideoPlayer.h Outdated
@OmarAglan

Copy link
Copy Markdown

@codex

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 6af80fb5a5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@xezon

xezon commented Sep 2, 2026

Copy link
Copy Markdown

The change title and description are outdated.

@CryoTheRenegade CryoTheRenegade changed the title bugfix(audio): Reapply Bink movie volume on first frame bugfix(audio): Apply configured volume to Bink movie audio Sep 2, 2026
@CryoTheRenegade

Copy link
Copy Markdown
Author

The change title and description are outdated.

updated

@xezon
xezon merged commit e2ad13b into TheSuperHackers:main Sep 2, 2026
23 checks passed
@CryoTheRenegade
CryoTheRenegade deleted the bugfix/2850-video-audio-volume branch September 4, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Audio Is audio related Bug Something is not working right, typically is user facing Minor Severity: Minor < Major < Critical < Blocker

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Video/movie audio ignores all volume settings (plays at full volume even when sliders are 0)

5 participants