Skip to content

SuvMusic v2.4.1.0

Choose a tag to compare

@github-actions github-actions released this 08 May 19:46
· 3064 commits to main since this release

SuvMusic v2.4.1.0

Release
Platform
License


Release Overview

  • Version: 2.4.1.0
  • Build Date: May 09, 2026
  • Target SDK: 36 (Android 15+)
  • Status: Stable Release

Implementation Details

  • Spotify-Style Volume Normalization: Replaced the old constant-gain shim with per-track perceptual loudness analysis. Each song's RMS is measured the first time it plays, cached locally, and used to apply a per-track gain offset (target ≈ -15 dBFS) so back-to-back tracks land at the same level — no more sudden jumps between a quiet ballad and a loud chart hit.
  • Robust Volume Boost: Capped the boost slider at +12 dB (was +15) with combined-gain clamp [-8, +14] dB, plus softer limiter params (threshold -0.3, ratio 12, attack 1ms, release 80ms) so the limiter colours the signal less while still preventing clipping.
  • Spatial Audio Intensity: New 'Spatial Intensity' slider (0–100%) drives both the static azimuth sweep and crossfeed strength independently of head-tracking sensitivity, so users on speakers or wired headphones now have a knob too.
  • Audio Offload Now Honoured: The 'Audio Offload' toggle in Playback settings is finally respected — previously the service would auto-enable offload regardless of the user's preference whenever no software effect was active.
  • Music Haptics from Real Audio: Replaced the synthetic 500ms beat with real-time RMS sampling from the native audio engine, plus an adaptive threshold (max of absolute floor and 60% of running peak) so haptics fire on quiet tracks and don't spam on loud ones. Toggling Music Haptics or changing mode/intensity now takes effect live without an app restart.
  • Music Languages Dialog Wired: Clicking 'Music Languages' in Playback Settings now actually shows the selection dialog (it was orphaned before). Expanded to 23 languages with proper YouTube hl-code mapping for richer localized recommendations.
  • Queue Reorder Polish: Bumped drag threshold so the row that snaps under the finger lines up cleanly after each swap (was visibly jumping ~8dp). Replaced the single-step if with a while loop tracking the working index locally so fast flicks walk through multiple rows instead of stalling on a stale captured index. Same fast-flick fix applied to the Playlist screen for consistency.
  • Swipe-Down-To-Dismiss Responsiveness: Lowered dismiss threshold from -10% to -5% of drag range so a confident flick reliably triggers it. Mini player now tracks the finger 1:1 with a fade as you pull down, and animates offscreen before stopping playback so the dismiss reads as motion rather than a hard cut. Toggle now takes effect live without restart.
  • High-Resolution Artwork on Home: Threaded covers, song rows, and playlist headers across HomeSections, PlaylistCard, AlbumScreen, and PlaylistScreen through ImageUtils.getHighResThumbnailUrl with explicit Coil request sizes. Previously several AsyncImage calls passed raw w120/w160 URLs so YouTube returned tiny stamps that pixellated on mid/large surfaces.
  • Instant Settings Account Header: Mirrored userName + userAvatar into encrypted prefs for synchronous read on entry. The Settings header now renders the current account immediately instead of flashing blank while DataStore reads complete.
  • Robust Announce Songs: Rewrote TTSManager around UtteranceProgressListener with AudioAttributes(USAGE_MEDIA, CONTENT_TYPE_SPEECH), STREAM_MUSIC, and per-utterance audio focus so announcements actually route through Bluetooth/BLE headsets correctly. Added three settings — TTS volume %, music duck volume %, and Bluetooth-only switch — with sliders. Player volume now reliably restores in onDone/onError, and a try/finally fallback ensures the player isn't stranded ducked when cancellation happens (e.g., next track starting before announcement finishes).
  • Bluetooth Autoplay Reliability: Debounce duplicate connect events between AudioDeviceCallback and ACL_CONNECTED, then verify play() actually started — some BT stacks miss the first call while the route is still settling, so retry up to three times with backoff.
  • AI Equalizer Critical Fixes:
    · OpenAI client was building a JSONObject and discarding it before sending a hand-templated string. Now uses proper JSONObject/JSONArray construction.
    · Restored AI state on app restart was set on _lastResult but never pushed to the audio engine. Now applies on init AND snapshots the pre-AI engine state so A/B Compare works after restart.
    · checkAndAutoApplyAIForSong took the 'before AI' snapshot AFTER applySettings — so Original and AI were identical. Snapshot is now captured first.
    · Auto mode was hardcoded to ChatProxy with empty key, ignoring the user's configured provider/model. Now resolves provider+key+model from settings with a graceful fallback to ChatProxy when no key is configured.
    · System prompt mislabelled limiterThresholdDb as 'Peak Level' and let the model wrap output in markdown. Reworded plus added an extractJsonObject() helper that strips ``` json fences across all four AI clients.

Contribution & Support

The development of SuvMusic is maintained through community support. If you find value in this project, consider supporting through the following channels:


Maintainer

Suvojeet Sengupta
Lead Android Developer
GitHub Profile
Email


This release was automatically generated as part of the SuvMusic continuous integration pipeline.