Browse Source

Ability to remove buses while they are being used on 2D and 3D stream players. Fixes #15115

Juan Linietsky 7 years ago
parent
commit
65111ba996

+ 12 - 0
scene/2d/audio_stream_player_2d.cpp

@@ -92,6 +92,9 @@ void AudioStreamPlayer2D::_mix_audio() {
 		int cc = AudioServer::get_singleton()->get_channel_count();
 
 		if (cc == 1) {
+			if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.bus_index, 0))
+				continue; //may have been removed
+
 			AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 0);
 
 			for (int j = 0; j < buffer_size; j++) {
@@ -102,11 +105,20 @@ void AudioStreamPlayer2D::_mix_audio() {
 
 		} else {
 			AudioFrame *targets[4];
+			bool valid = true;
 
 			for (int k = 0; k < cc; k++) {
+				if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.bus_index, k)) {
+					valid = false; //may have been removed
+					break;
+				}
+
 				targets[k] = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, k);
 			}
 
+			if (!valid)
+				continue;
+
 			for (int j = 0; j < buffer_size; j++) {
 
 				AudioFrame frame = buffer[j] * vol;

+ 6 - 1
scene/3d/audio_stream_player_3d.cpp

@@ -112,8 +112,10 @@ void AudioStreamPlayer3D::_mix_audio() {
 			AudioFrame vol_inc = (target_volume - vol_prev) / float(buffer_size);
 			AudioFrame vol = stream_paused_fade_in ? AudioFrame(0.f, 0.f) : current.vol[k];
 
-			AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, k);
+			if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.bus_index, k))
+				continue; //may have been deleted, will be updated on process
 
+			AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, k);
 			current.filter.set_mode(AudioFilterSW::HIGHSHELF);
 			current.filter.set_sampling_rate(AudioServer::get_singleton()->get_mix_rate());
 			current.filter.set_cutoff(attenuation_filter_cutoff_hz);
@@ -159,6 +161,9 @@ void AudioStreamPlayer3D::_mix_audio() {
 
 			if (current.reverb_bus_index >= 0) {
 
+				if (!AudioServer::get_singleton()->thread_has_channel_mix_buffer(current.reverb_bus_index, k))
+					continue; //may have been deleted, will be updated on process
+
 				AudioFrame *rtarget = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.reverb_bus_index, k);
 
 				if (current.reverb_bus_index == prev_outputs[i].reverb_bus_index) {

+ 8 - 0
servers/audio_server.cpp

@@ -460,6 +460,14 @@ void AudioServer::_mix_step() {
 	to_mix = buffer_size;
 }
 
+bool AudioServer::thread_has_channel_mix_buffer(int p_bus, int p_buffer) const {
+	if (p_bus < 0 || p_bus >= buses.size())
+		return false;
+	if (p_buffer < 0 || p_buffer >= buses[p_bus]->channels.size())
+		return false;
+	return true;
+}
+
 AudioFrame *AudioServer::thread_get_channel_mix_buffer(int p_bus, int p_buffer) {
 
 	ERR_FAIL_INDEX_V(p_bus, buses.size(), NULL);

+ 1 - 0
servers/audio_server.h

@@ -282,6 +282,7 @@ public:
 	}
 
 	//do not use from outside audio thread
+	bool thread_has_channel_mix_buffer(int p_bus, int p_buffer) const;
 	AudioFrame *thread_get_channel_mix_buffer(int p_bus, int p_buffer);
 	int thread_get_mix_buffer_size() const;
 	int thread_find_bus_index(const StringName &p_name);