Skip to content

Audio System

Deepratna Awale edited this page Oct 6, 2026 · 3 revisions

Audio system

How Open Wallpaper Engine hears your Mac's sound and turns it into Wallpaper Engine's audio spectrum, and how wallpapers' own sound is played. Code lives in Audio/, Scene/Sound/ and Scene/Scripting/Media/.

Capture

  • SystemAudioCapture captures system audio with a Core Audio process tap on macOS 14.2+ (System Audio Recording permission), or with ScreenCaptureKit (Screen Recording) before that or when the tap can't start (SystemAudioBackend). It is owned by WallpaperServices, and at most one capture exists app-wide; it runs only while something needs audio (AudioCaptureDemand).
  • It never starts a capture while its permission is missing (ScreenCaptureKit would show the system prompt itself). The prompt appears only from Grant Access (PermissionHelper); AudioCapturePermissionGate starts capture once the grant appears, with no restart needed.
  • CaptureRestartScheduler restarts the stream after it stops (sleep/wake, errors), so audio reactivity survives sleep.
  • AudioLevelTap taps individual players (per-item levels).

The spectrum

WE's spectrum is computed the way WE computes it, in stereo:

  1. On the audio thread, AudioSpectrumBlockTransform (with BluesteinDFT) turns blocks of samples into raw band values.
  2. AudioSpectrumFeed holds the latest raw block (64 left, 64 right) shared by every consumer, and the last frame a scene published for readers that don't advance.
  3. Each consumer owns an AudioSpectrumClock with its own AudioSpectrumSmoothing, stepped by its own frames.

Why per-consumer clocks: WE smooths once per frame of the thing that shows the values. Stepping one shared state from several consumers would advance it several times a frame, and a consumer nobody else advances (a lone web page) would never move.

Consumer Gets
Scene shaders g_AudioSpectrum{16,32,64}{Left,Right}
SceneScript engine.registerAudioBuffers left/right/average arrays (16/32/64)
Particles Audio response on rates and operators
Web wallpapers 128 values (64 left, 64 right) about 30 times a second
Video music sync The overall level, driving zoom, tilt and saturation

The playback rate scales the analyser's step, as it scales everything on the SceneClock.

Sound layers

Scene/Sound plays WE's sound layers on the scene's clock: modes, gain, timers, mute and pause, script control (SceneSoundLayers, SceneSoundMixer, SceneSoundVoices) and spatial sound placed as in WE (SceneSoundSpatialization).

WallpaperAudioRouting makes each running wallpaper play its sound once; Audio Output in Settings silences all, and the menu bar's volume and mute apply to all.

Now Playing

  • NowPlayingBackend picks the source. On macOS 15.4+, MediaRemote answers only entitled processes, so nowPlayingAdapter.pl streams the session from /usr/bin/perl through Apple's PerlObjCBridge (nothing compiled or installed; the script is a resource, not an executable). Before 15.4, MediaRemote is used directly.
  • MediaSessionSource feeds SceneScript's media callbacks and web wallpapers' media listeners (WebWallpaperMediaBridge), including the thumbnail's colours (ArtworkPalette).
  • Gated by Media integration support (WE's mediaintegration).

Tests

AudioSpectrumTests, the web and SceneScript media tests, and ScenePlaybackEaseTests for the sound timers. See Testing.

User guide: Settings › Plugins, Permissions, Diagnostics, About and Scene wallpapers

Clone this wiki locally