Prechádzať zdrojové kódy

Merge pull request #23175 from marcelofg55/input_buffer_fix

Fix possible audio input buffer issues
Rémi Verschelde 6 rokov pred
rodič
commit
8a113b9143

+ 2 - 3
drivers/coreaudio/audio_driver_coreaudio.cpp

@@ -145,9 +145,6 @@ Error AudioDriverCoreAudio::init() {
 	unsigned int buffer_size = buffer_frames * channels;
 	samples_in.resize(buffer_size);
 	input_buf.resize(buffer_size);
-	input_buffer.resize(buffer_size * 8);
-	input_position = 0;
-	input_size = 0;
 
 	print_verbose("CoreAudio: detected " + itos(channels) + " channels");
 	print_verbose("CoreAudio: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
@@ -487,6 +484,8 @@ void AudioDriverCoreAudio::capture_finish() {
 
 Error AudioDriverCoreAudio::capture_start() {
 
+	input_buffer_init(buffer_frames);
+
 	OSStatus result = AudioOutputUnitStart(input_unit);
 	if (result != noErr) {
 		ERR_PRINTS("AudioOutputUnitStart failed, code: " + itos(result));

+ 8 - 10
drivers/pulseaudio/audio_driver_pulseaudio.cpp

@@ -613,20 +613,18 @@ Error AudioDriverPulseAudio::capture_init_device() {
 			break;
 	}
 
-	print_verbose("PulseAudio: detected " + itos(pa_rec_map.channels) + " input channels");
-
 	pa_sample_spec spec;
 
 	spec.format = PA_SAMPLE_S16LE;
 	spec.channels = pa_rec_map.channels;
 	spec.rate = mix_rate;
 
-	int latency = 30;
-	input_buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
-	int buffer_size = input_buffer_frames * spec.channels;
+	int input_latency = 30;
+	int input_buffer_frames = closest_power_of_2(input_latency * mix_rate / 1000);
+	int input_buffer_size = input_buffer_frames * spec.channels;
 
 	pa_buffer_attr attr;
-	attr.fragsize = buffer_size * sizeof(int16_t);
+	attr.fragsize = input_buffer_size * sizeof(int16_t);
 
 	pa_rec_str = pa_stream_new(pa_ctx, "Record", &spec, &pa_rec_map);
 	if (pa_rec_str == NULL) {
@@ -642,9 +640,10 @@ Error AudioDriverPulseAudio::capture_init_device() {
 		ERR_FAIL_V(ERR_CANT_OPEN);
 	}
 
-	input_buffer.resize(input_buffer_frames * 8);
-	input_position = 0;
-	input_size = 0;
+	input_buffer_init(input_buffer_frames);
+
+	print_verbose("PulseAudio: detected " + itos(pa_rec_map.channels) + " input channels");
+	print_verbose("PulseAudio: input buffer frames: " + itos(input_buffer_frames) + " calculated latency: " + itos(input_buffer_frames * 1000 / mix_rate) + "ms");
 
 	return OK;
 }
@@ -760,7 +759,6 @@ AudioDriverPulseAudio::AudioDriverPulseAudio() {
 
 	mix_rate = 0;
 	buffer_frames = 0;
-	input_buffer_frames = 0;
 	pa_buffer_size = 0;
 	channels = 0;
 	pa_ready = 0;

+ 0 - 1
drivers/pulseaudio/audio_driver_pulseaudio.h

@@ -64,7 +64,6 @@ class AudioDriverPulseAudio : public AudioDriver {
 
 	unsigned int mix_rate;
 	unsigned int buffer_frames;
-	unsigned int input_buffer_frames;
 	unsigned int pa_buffer_size;
 	int channels;
 	int pa_ready;

+ 1 - 4
drivers/wasapi/audio_driver_wasapi.cpp

@@ -336,10 +336,7 @@ Error AudioDriverWASAPI::init_capture_device(bool reinit) {
 	HRESULT hr = audio_input.audio_client->GetBufferSize(&max_frames);
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 
-	// Set the buffer size
-	input_buffer.resize(max_frames * CAPTURE_BUFFER_CHANNELS);
-	input_position = 0;
-	input_size = 0;
+	input_buffer_init(max_frames);
 
 	return OK;
 }

+ 13 - 3
servers/audio/audio_stream.cpp

@@ -136,16 +136,20 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
 
 	Vector<int32_t> buf = AudioDriver::get_singleton()->get_input_buffer();
 	unsigned int input_size = AudioDriver::get_singleton()->get_input_size();
+	int mix_rate = AudioDriver::get_singleton()->get_mix_rate();
+	int playback_delay = MIN(((50 * mix_rate) / 1000) * 2, buf.size() >> 1);
+#ifdef DEBUG_ENABLED
+	unsigned int input_position = AudioDriver::get_singleton()->get_input_position();
+#endif
 
-	// p_frames is multiplied by two since an AudioFrame is stereo
-	if ((p_frames + MICROPHONE_PLAYBACK_DELAY * 2) > input_size) {
+	if (playback_delay > input_size) {
 		for (int i = 0; i < p_frames; i++) {
 			p_buffer[i] = AudioFrame(0.0f, 0.0f);
 		}
 		input_ofs = 0;
 	} else {
 		for (int i = 0; i < p_frames; i++) {
-			if (input_size >= input_ofs) {
+			if (input_size > input_ofs) {
 				float l = (buf[input_ofs++] >> 16) / 32768.f;
 				if (input_ofs >= buf.size()) {
 					input_ofs = 0;
@@ -162,6 +166,12 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
 		}
 	}
 
+#ifdef DEBUG_ENABLED
+	if (input_ofs > input_position && (input_ofs - input_position) < (p_frames * 2)) {
+		print_verbose(String(get_class_name()) + " buffer underrun: input_position=" + itos(input_position) + " input_ofs=" + itos(input_ofs) + " input_size=" + itos(input_size));
+	}
+#endif
+
 	AudioDriver::get_singleton()->unlock();
 }
 

+ 0 - 2
servers/audio/audio_stream.h

@@ -122,8 +122,6 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
 	GDCLASS(AudioStreamPlaybackMicrophone, AudioStreamPlayback)
 	friend class AudioStreamMicrophone;
 
-	static const int MICROPHONE_PLAYBACK_DELAY = 256;
-
 	bool active;
 	unsigned int input_ofs;
 

+ 8 - 0
servers/audio_server.cpp

@@ -80,6 +80,14 @@ double AudioDriver::get_mix_time() const {
 	return total;
 }
 
+void AudioDriver::input_buffer_init(int driver_buffer_frames) {
+
+	const int input_buffer_channels = 2;
+	input_buffer.resize(driver_buffer_frames * input_buffer_channels * 4);
+	input_position = 0;
+	input_size = 0;
+}
+
 void AudioDriver::input_buffer_write(int32_t sample) {
 
 	input_buffer.write[input_position++] = sample;

+ 1 - 0
servers/audio_server.h

@@ -59,6 +59,7 @@ protected:
 
 	void audio_server_process(int p_frames, int32_t *p_buffer, bool p_update_mix_time = true);
 	void update_mix_time(int p_frames);
+	void input_buffer_init(int driver_buffer_frames);
 	void input_buffer_write(int32_t sample);
 
 #ifdef DEBUG_ENABLED