`.clear_buffer()` causes error 'Condition "active" is true'

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jmaros

I have the following script to play audio from an array:

var should_play = $PlaybackSwitch.active and source != null
if should_play:
	var empty_frames = playback.get_frames_available()
	while empty_frames > 0:
		playback.push_frame(source.audio_data[playback_index])
		playback_index += 1
		empty_frames -= 1
if should_play and not $Player.playing:
	playback.clear_buffer()
	$Player.play()
if not should_play and $Player.playing:
	$Player.stop()
	playback_index = 0

But I have the problem that when I stop and restart playback, a snippet of audio from the end of what was previously playing makes it in. Calling clear_buffer is supposed to help with this, but it produces the error Condition "active" is true. Looking at the C++ source, I can’t figure out where this is getting set. What do I need to do to make the stream not active so I can clear it?

Just guessing here, but is this as intended?

var should_play = playing and source != null

So, should_play is only set if the track is already playing?

Should that not be !playing and source != null?

jgodfrey | 2022-09-26 20:15

Also, it seems odd that you might start the track playing with…

$Player.play()

and then start mucking around with the audio frames via:

playback.push_frame(...)

jgodfrey | 2022-09-26 20:20

playing is poorly named, it is a boolean used by an on/off switch. Maybe should_play or play_requested would be more appropriate.

jmaros | 2022-09-26 20:20

Yeah, putting Player.play after the generation would make sense.

jmaros | 2022-09-26 20:21

I’ve updated the code accordingly.

jmaros | 2022-09-26 20:24

Seems like you could still arrive at the posted code with the source already playing and end up setting should_play = true. In that case, you’d still be fiddling with the frames of a currently playing audio source - which seems likely to be the cause of the original issue (?).

Should should_play only be set if the source isn’t already playing? That’d eliminate the possibility described above…

But, really just guessing here…

jgodfrey | 2022-09-26 20:33

The example of how to use the classes I’m using does this. There is no other code that plays the audio source, and it is not set to auto-play, so it can only be started and stopped by this particular piece of code. As far as I can tell the problem is with playback.clear_buffer(). It is only called while the audio source is stopped but still produces the error mentioned. Looking at the C++ code, clear_buffer never actually gets to the part of the code that clears the buffer if the error is triggered.

jmaros | 2022-09-26 20:44

:bust_in_silhouette: Reply From: jmaros

For now I’ve “fixed” this by creating a new stream every time playback stops:

var should_play = $PlaybackSwitch.active and source != null
if should_play:
	var empty_frames = playback.get_frames_available()
	while empty_frames > 0:
		playback.push_frame(source.audio_data[playback_index])
		playback_index += 1
		empty_frames -= 1
if should_play and not $Player.playing:
	$Player.play()
if not should_play and $Player.playing:
	$Player.stop()
	playback_index = 0
	$Player.stream = AudioStreamGenerator.new()
	playback = $Player.get_stream_playback()