godot icon indicating copy to clipboard operation
godot copied to clipboard

Add `volume_linear` property and getter/setter methods for audio-related classes

Open Meorge opened this issue 3 months ago • 6 comments

This PR implements the backend side for https://github.com/godotengine/godot-proposals/issues/1884 (but does not fully close it).

  • It adds the property volume_linear to AudioStreamPlayer, AudioStreamPlayer2D, AudioStreamPlayer3D, and AudioEffectAmplify (including the setter set_volume_linear and getter get_volume_linear).
  • It adds the property volume_linear for every bus within an AudioBusLayout.
  • It adds the getter get_bus_volume_linear and setter set_bus_volume_linear to AudioServer. (Because it requires an argument for the bus index, it can't be made into a property.)

Internally, it simply wraps the volume_db properties with linear_to_db and db_to_linear calls. However, having these as properties with built-in getters and setters has some nice benefits:

  • A volume slider can be constructed easily and without having to write any code, by hooking the Range.value_changed signal up to set_volume_linear.
  • My personal favorite: a Tween can be used to smoothly fade music or sounds in and out with an AudioStreamPlayer:
func _fade_with_volume_linear():
    var tween = create_tween()

    # Fade music out over 2 seconds
    tween.tween_property(%MusicPlayer, "volume_linear", 0.0, 2.0)
    tween.tween_interval(3.0)
    # Fade music in over 2 seconds
    tween.tween_property(%MusicPlayer, "volume_linear", 1.0, 2.0)


func _fade_without_volume_linear():
    var tween = create_tween()

    # Fade music out over 2 seconds
    tween.tween_method(func(v): %MusicPlayer.volume_db = linear_to_db(v), db_to_linear(%MusicPlayer.volume_db), 0.0, 2.0)
    tween.tween_interval(3.0)
    # Fade music in over 2 seconds
    # (Note that the `from` argument is likely to catch people off-guard!)
    tween.tween_method(func(v): %MusicPlayer.volume_db = linear_to_db(v), 0.0, 1.0, 2.0)
  • As seen in https://github.com/godotengine/godot-proposals/issues/1884, while dB may technically be more "proper", a linear scale is what a lot of people intuitively think of for controlling and representing volume, so providing an easier interface to that is a good thing 🙂

[!NOTE] This PR does not implement any frontend/inspector behavior. Users will still only be able to modify the volume in the inspector in dBs. If desired, it would be trivial to expose "Volume Linear" underneath "Volume dB" in the inspector. However this would take up twice as much space in the inspector for what is effectively the same value. In the long run, I think it'd be best to include a custom input field that can switch between dB and the linear scale, as suggested in the proposal. Because this PR doesn't implement this (currently), I don't feel it would close that proposal.

Meorge avatar Nov 15 '24 07:11 Meorge