Sounds play on flutter_soloud instead of three mpv players
SoundEngine (platform/audio) opens the device once (2 s after start, or on the first sound), loads each synthesized sound into memory (no temp files), plays overlapping voices and is disposed on window close, before leaving the server. The SfxService interface and its callers are unchanged; loudness matches the old mpv path (v^6). WAV only, so no codec libraries are bundled and no build packages are needed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fd8064611a
commit
b949951ef9
13 files changed
+436
-77
No files matched your search
+12
-5
@@ -335,7 +335,7 @@ menu and Settings say so). Otherwise the session player logs at `warn`
|
||||
on media_kit's handle): media_kit drains mpv's log on the UI thread, one
|
||||
message at a time, so a chatty level, or ffmpeg logging every retry of a
|
||||
refused request, could starve the UI. Shader and yt-dlp hook errors are
|
||||
`error` lines and still arrive. The thumbnail and sound players keep
|
||||
`error` lines and still arrive. The thumbnail players keep
|
||||
media_kit's default (`error`) and nothing listens to their log. The hardware path is
|
||||
fragile: media_kit borrows whatever EGL context GDK left current on the main
|
||||
thread (upstream media-kit#1404), so an X11 session or a Flutter/GDK change
|
||||
@@ -1261,10 +1261,17 @@ panel) and chat messages (Copy message, and a link in it).
|
||||
dark space reverb) to quiet WAVs; `sound_bank.dart` voices every event
|
||||
in three presets (`SoundPreset`: Cosmic, Abyss, Wood & glass) in one
|
||||
shared key, so mixed presets still agree. `SynthSfx` renders a sound on
|
||||
first use into the temp dir (cache key: preset, sound, ready index) and
|
||||
plays it on a pool of three audio-only mpv players, at
|
||||
`AppSettings.soundVolume` (square curve) unless switched off in
|
||||
`soundsOff`. Settings → Notifications & sounds has the volume, the
|
||||
first use (on a worker isolate, to WAV bytes in memory) and hands it to
|
||||
`SoundEngine` (`platform/audio/sound_engine.dart`), which loads it into
|
||||
flutter_soloud (SoLoud mixing into a miniaudio output device; voices
|
||||
overlap) once per slot (sound and ready index); a different preset in a
|
||||
slot replaces and frees the old sound. Each play is at
|
||||
`AppSettings.soundVolume` (as v^6, SoLoud's linear gain: the square curve times mpv's cubic volume the sounds used to play through, so the slider sounds as before) unless
|
||||
switched off in `soundsOff`. The device opens 2 s after startup
|
||||
(`warmUp`), so neither startup nor the first sound waits on it; if it
|
||||
can't open, the engine logs `no sounds: audio init failed` once and drops
|
||||
every play. The close path disposes the engine (deinit, 500 ms bound)
|
||||
before leaving the server. Settings → Notifications & sounds has the volume, the
|
||||
overall sound set (`soundPreset`), and per sound a preview, its own set
|
||||
(`soundPresetFor`, else the overall one) and a switch; a preview always
|
||||
re-renders, so an edited spec plays after a hot reload.
|
||||
|
||||
+9
-2
@@ -6,7 +6,11 @@ Layout and rules: [ARCHITECTURE.md](ARCHITECTURE.md).
|
||||
|
||||
Needs the Flutter SDK (beta channel, Dart 3.13+) and, for the Linux desktop
|
||||
build, the usual GTK toolchain (clang, cmake, ninja, pkg-config, libgtk-3-dev).
|
||||
mpv libraries come from `media_kit_libs_video`. `fox_utils` (drag & drop,
|
||||
mpv libraries come from `media_kit_libs_video`. `flutter_soloud` (the app's
|
||||
sounds) compiles SoLoud and miniaudio from source in its build hook with
|
||||
that C++ toolchain (MSVC on Windows); it needs no audio dev headers (miniaudio
|
||||
loads ALSA / PulseAudio / JACK at run time) and, with `no_xiph_libs` set in
|
||||
the desktop pubspec, downloads nothing. `fox_utils` (drag & drop,
|
||||
clipboard files and images; native Linux/Windows plugin) is the owner's
|
||||
shared package, a git dependency pinned to a tag of
|
||||
`git.senkochan.moe/Foxyz/fox_utils`: bump it by tagging there and changing
|
||||
@@ -67,6 +71,9 @@ and `e2e_check` (simulated viewers against a live server).
|
||||
media_kit "S/W rendering" because they have no display; that says nothing
|
||||
about the app. Run only tests related to
|
||||
what you changed.
|
||||
- `sound_device_e2e` opens the real audio device (flutter_soloud) and plays
|
||||
every sound of every preset quietly (`WT_SFX_VOLUME`, default 0.1);
|
||||
`sound_engine_test` covers the engine with a fake backend.
|
||||
- CI (`.gitea/workflows/ci.yml`): analyze + test for core and server, plus
|
||||
`dart compile exe` of the dedicated server (fails if Flutter creeps into
|
||||
`packages/server`). Desktop tests are not in CI.
|
||||
@@ -184,7 +191,7 @@ slow to come up shows mpv's error with "no HTTP error logged".
|
||||
- media_kit has no public `Player.setProperty`; the code reaches mpv through a
|
||||
dynamic call on `player.platform`. Cache size goes through
|
||||
`PlayerConfiguration(bufferSize:)`.
|
||||
- Hot restart with any media_kit `Player` alive (session, thumbnails, sfx)
|
||||
- Hot restart with any media_kit `Player` alive (session, thumbnails)
|
||||
used to SIGSEGV on mpv's `core` thread: each mpv handle's wakeup callback
|
||||
is a `NativeCallable` of the old isolate, freed by the restart, and media_kit
|
||||
then sends the leftover handles `quit`, which fires it. `fox_utils`' Linux
|
||||
|
||||
Reference in new issue
Block a user