make fade_in/fade_out idempotent — repeat calls toward the same target are no-ops
Without this, scripts that re-fire fade_in on every Area2D body_entered (or similar repeating signal) restart the fade clock each call, which can stutter audibly when a per-song crossfade is also running. Now a fade_in while already fading to the user's set level — or fade_out while already fading to silent — is a no-op. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5204295864
commit
7bcc12b45b
|
|
@ -90,11 +90,11 @@ When the node enters the tree in the editor, `stream` is auto-assigned an `Audio
|
|||
| `pause()` | Pauses playback. No-op if not playing or already paused. |
|
||||
| `resume()` | Resumes playback after a pause. |
|
||||
| `is_song_playing() -> bool` | True iff a song's layers are active and not paused. Distinct from `is_playing()`, which stays true between songs because the polyphonic playback session itself is still live. |
|
||||
| `fade_in(duration: float)` | Animates `volume_db` up to the user's set level over `duration` seconds. **Pure volume operation** — does not start playback, unpause, or otherwise change playing state. The "set level" is the last value written to `volume_db` outside of an active fade, so `fade_in` → `fade_out` → `fade_in` round-trips back to the original volume. If any fade is in flight (player-wide `fade_out` or per-song crossfade from `SkipMode = CrossFade`), the ramp continues from the current `volume_db` so audible state is preserved. Otherwise it snaps to silent and ramps up. Pair with `play_playlist()` / `resume()` if the player isn't already playing. |
|
||||
| `fade_out(duration: float)` | Animates `volume_db` from its current value down to silent over `duration` seconds. **Pure volume operation** — does not stop the polyphonic session or pause. Call `pause()` / `stop()` yourself afterwards if you want playback to halt. |
|
||||
| `fade_in(duration: float)` | Animates `volume_db` up to the user's set level over `duration` seconds. **Pure volume operation** — does not start playback, unpause, or otherwise change playing state. The "set level" is the last value written to `volume_db` outside of an active fade, so `fade_in` → `fade_out` → `fade_in` round-trips back to the original volume. If any fade is in flight (player-wide `fade_out` or per-song crossfade from `SkipMode = CrossFade`), the ramp continues from the current `volume_db` so audible state is preserved. Otherwise it snaps to silent and ramps up. **Idempotent** — calling it while already fading to the same target is a no-op (won't restart the fade clock). Pair with `play_playlist()` / `resume()` if the player isn't already playing. |
|
||||
| `fade_out(duration: float)` | Animates `volume_db` from its current value down to silent over `duration` seconds. **Pure volume operation** — does not stop the polyphonic session or pause. Call `pause()` / `stop()` yourself afterwards if you want playback to halt. **Idempotent** — calling it while already fading to silent is a no-op. |
|
||||
| `get_current_song_index() -> int` | Index of the song most recently kicked off in `Playlist.QueuedSongs`. During a reverb-tail crossover this becomes the incoming song the moment it starts, even though the outgoing song is still audible. |
|
||||
| `advance_to_next_song()` | Skip to the next song in the playlist (wraps from the end back to index 0). Transition style is controlled by `SkipMode`. |
|
||||
| `advance_to_track(index: int)` | Same as `advance_to_next_song`, but jumps to a specific index. Out-of-range indices are ignored. |
|
||||
| `advance_to_track(index: int)` | Same as `advance_to_next_song`, but jumps to a specific index. Out-of-range indices are ignored. **No-op when called with the index of the song already playing** — won't restart it. |
|
||||
|
||||
#### Behaviour
|
||||
|
||||
|
|
|
|||
|
|
@ -176,10 +176,13 @@ func advance_to_track(index: int) -> void:
|
|||
## crossfade), the ramp continues from the current [code]volume_db[/code] —
|
||||
## no snap to silent, so audible crossfade state is preserved. Otherwise the
|
||||
## ramp snaps to silent first and rises to the user's set level.
|
||||
## Idempotent: no-op if a fade is already heading to this same target.
|
||||
func fade_in(duration: float) -> void:
|
||||
var target_db : float = _target_volume_db;
|
||||
if target_db <= _FADE_SILENT_DB + 0.001:
|
||||
target_db = 0.0;
|
||||
if _fading and is_equal_approx(_fade_to_db, target_db):
|
||||
return;
|
||||
var any_song_fading : bool = false;
|
||||
for active in _active_songs:
|
||||
if active.fading:
|
||||
|
|
@ -192,7 +195,10 @@ func fade_in(duration: float) -> void:
|
|||
## [param duration] seconds. Pure volume operation — does not stop the
|
||||
## polyphonic session or pause. Call [method pause] or [code]stop()[/code]
|
||||
## yourself if you want playback to halt at the end.
|
||||
## Idempotent: no-op if a fade is already heading to silent.
|
||||
func fade_out(duration: float) -> void:
|
||||
if _fading and is_equal_approx(_fade_to_db, _FADE_SILENT_DB):
|
||||
return;
|
||||
_start_fade(_player.volume_db, _FADE_SILENT_DB, duration);
|
||||
|
||||
func apply_stream_volumes(value: float) -> void:
|
||||
|
|
|
|||
Loading…
Reference in New Issue