I have 2D subviewport embedded in my 3D scene, much like the 2d in 3d godot demo project. In my case the 2D scene is a video player to represent a television.
Any audio generated in the subviewport however is played directly through the main bus as if the whole game is 2D. Instead I would like the quad rendering the viewport texture to act like an AudioStreamPlayer3D, capture the audio from the embedded 2D scene and broadcast it in 3D space.
I’ve managed to hack a temporary solution by pulling the audio out of the video file and manually sticking it in a AudioStreamPlayer3D, but ideally I would like a solution that works more generally, e.g. for embedding 2D games on a “tv” in 3D space.
If I bust out the C++ I’m sure after a lot of work I could write something to handle it, but is there an existing solution out there I’m missing? I’ve already experimented with AudioListener2D/3D but they don’t seem to do what I want.
extends AudioStreamPlayer3D
var capture:AudioEffectCapture
var playback:AudioStreamGeneratorPlayback
func _ready():
var capture_bus_idx = AudioServer.get_bus_index(&"Capture")
capture = AudioServer.get_bus_effect(capture_bus_idx, 0)
stream = AudioStreamGenerator.new()
play()
playback = get_stream_playback()
fill_buffer()
func _process(delta: float) -> void:
fill_buffer()
func fill_buffer():
var playback_available = playback.get_frames_available()
var capture_available = capture.get_frames_available()
# Fill the playback buffer until we run out of captured frames or playback frames
while playback_available > capture_available:
var buffer = capture.get_buffer(capture_available)
playback.push_buffer(buffer)
playback_available -= capture_available
if playback_available <= 0:
break
capture_available = capture.get_frames_available()
if capture_available <= 0:
break