Browse Source

Corrections to audio buffer size calculations

Marcelo Fernandez 8 years ago
parent
commit
f231eadc9e

+ 13 - 6
drivers/alsa/audio_driver_alsa.cpp

@@ -31,6 +31,7 @@
 
 
 #ifdef ALSA_ENABLED
 #ifdef ALSA_ENABLED
 
 
+#include "os/os.h"
 #include "project_settings.h"
 #include "project_settings.h"
 
 
 #include <errno.h>
 #include <errno.h>
@@ -44,7 +45,7 @@ Error AudioDriverALSA::init() {
 	samples_in = NULL;
 	samples_in = NULL;
 	samples_out = NULL;
 	samples_out = NULL;
 
 
-	mix_rate = GLOBAL_DEF("audio/mix_rate", 44100);
+	mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
 	speaker_mode = SPEAKER_MODE_STEREO;
 	speaker_mode = SPEAKER_MODE_STEREO;
 	channels = 2;
 	channels = 2;
 
 
@@ -86,19 +87,25 @@ Error AudioDriverALSA::init() {
 	status = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &mix_rate, NULL);
 	status = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &mix_rate, NULL);
 	CHECK_FAIL(status < 0);
 	CHECK_FAIL(status < 0);
 
 
-	int latency = GLOBAL_DEF("audio/output_latency", 25);
-	buffer_size = closest_power_of_2(latency * mix_rate / 1000);
+	// In ALSA the period size seems to be the one that will determine the actual latency
+	// Ref: https://www.alsa-project.org/main/index.php/FramesPeriods
+	unsigned int periods = 2;
+	int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+	buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
+	buffer_size = buffer_frames * periods;
+	period_size = buffer_frames;
 
 
 	// set buffer size from project settings
 	// set buffer size from project settings
 	status = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size);
 	status = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size);
 	CHECK_FAIL(status < 0);
 	CHECK_FAIL(status < 0);
 
 
-	// make period size 1/8
-	period_size = buffer_size >> 3;
 	status = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &period_size, NULL);
 	status = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &period_size, NULL);
 	CHECK_FAIL(status < 0);
 	CHECK_FAIL(status < 0);
 
 
-	unsigned int periods = 2;
+	if (OS::get_singleton()->is_stdout_verbose()) {
+		print_line("audio buffer frames: " + itos(period_size) + " calculated latency: " + itos(period_size * 1000 / mix_rate) + "ms");
+	}
+
 	status = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &periods, NULL);
 	status = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &periods, NULL);
 	CHECK_FAIL(status < 0);
 	CHECK_FAIL(status < 0);
 
 

+ 1 - 0
drivers/alsa/audio_driver_alsa.h

@@ -51,6 +51,7 @@ class AudioDriverALSA : public AudioDriver {
 	unsigned int mix_rate;
 	unsigned int mix_rate;
 	SpeakerMode speaker_mode;
 	SpeakerMode speaker_mode;
 
 
+	snd_pcm_uframes_t buffer_frames;
 	snd_pcm_uframes_t buffer_size;
 	snd_pcm_uframes_t buffer_size;
 	snd_pcm_uframes_t period_size;
 	snd_pcm_uframes_t period_size;
 	int channels;
 	int channels;

+ 31 - 13
drivers/pulseaudio/audio_driver_pulseaudio.cpp

@@ -33,6 +33,7 @@
 
 
 #include <pulse/error.h>
 #include <pulse/error.h>
 
 
+#include "os/os.h"
 #include "project_settings.h"
 #include "project_settings.h"
 
 
 Error AudioDriverPulseAudio::init() {
 Error AudioDriverPulseAudio::init() {
@@ -44,7 +45,7 @@ Error AudioDriverPulseAudio::init() {
 	samples_in = NULL;
 	samples_in = NULL;
 	samples_out = NULL;
 	samples_out = NULL;
 
 
-	mix_rate = GLOBAL_DEF("audio/mix_rate", 44100);
+	mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
 	speaker_mode = SPEAKER_MODE_STEREO;
 	speaker_mode = SPEAKER_MODE_STEREO;
 	channels = 2;
 	channels = 2;
 
 
@@ -53,12 +54,17 @@ Error AudioDriverPulseAudio::init() {
 	spec.channels = channels;
 	spec.channels = channels;
 	spec.rate = mix_rate;
 	spec.rate = mix_rate;
 
 
-	int latency = GLOBAL_DEF("audio/output_latency", 25);
-	buffer_size = closest_power_of_2(latency * mix_rate / 1000);
+	int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+	buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
+	buffer_size = buffer_frames * channels;
+
+	if (OS::get_singleton()->is_stdout_verbose()) {
+		print_line("audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
+	}
 
 
 	pa_buffer_attr attr;
 	pa_buffer_attr attr;
-	// set to appropriate buffer size from global settings
-	attr.tlength = buffer_size;
+	// set to appropriate buffer length (in bytes) from global settings
+	attr.tlength = buffer_size * sizeof(int16_t);
 	// set them to be automatically chosen
 	// set them to be automatically chosen
 	attr.prebuf = (uint32_t)-1;
 	attr.prebuf = (uint32_t)-1;
 	attr.maxlength = (uint32_t)-1;
 	attr.maxlength = (uint32_t)-1;
@@ -80,8 +86,8 @@ Error AudioDriverPulseAudio::init() {
 		ERR_FAIL_COND_V(pulse == NULL, ERR_CANT_OPEN);
 		ERR_FAIL_COND_V(pulse == NULL, ERR_CANT_OPEN);
 	}
 	}
 
 
-	samples_in = memnew_arr(int32_t, buffer_size * channels);
-	samples_out = memnew_arr(int16_t, buffer_size * channels);
+	samples_in = memnew_arr(int32_t, buffer_size);
+	samples_out = memnew_arr(int16_t, buffer_size);
 
 
 	mutex = Mutex::create();
 	mutex = Mutex::create();
 	thread = Thread::create(AudioDriverPulseAudio::thread_func, this);
 	thread = Thread::create(AudioDriverPulseAudio::thread_func, this);
@@ -106,18 +112,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
 
 
 	while (!ad->exit_thread) {
 	while (!ad->exit_thread) {
 		if (!ad->active) {
 		if (!ad->active) {
-			for (unsigned int i = 0; i < ad->buffer_size * ad->channels; i++) {
+			for (unsigned int i = 0; i < ad->buffer_size; i++) {
 				ad->samples_out[i] = 0;
 				ad->samples_out[i] = 0;
 			}
 			}
 
 
 		} else {
 		} else {
 			ad->lock();
 			ad->lock();
 
 
-			ad->audio_server_process(ad->buffer_size, ad->samples_in);
+			ad->audio_server_process(ad->buffer_frames, ad->samples_in);
 
 
 			ad->unlock();
 			ad->unlock();
 
 
-			for (unsigned int i = 0; i < ad->buffer_size * ad->channels; i++) {
+			for (unsigned int i = 0; i < ad->buffer_size; i++) {
 				ad->samples_out[i] = ad->samples_in[i] >> 16;
 				ad->samples_out[i] = ad->samples_in[i] >> 16;
 			}
 			}
 		}
 		}
@@ -125,7 +131,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
 		// pa_simple_write always consumes the entire buffer
 		// pa_simple_write always consumes the entire buffer
 
 
 		int error_code;
 		int error_code;
-		int byte_size = ad->buffer_size * sizeof(int16_t) * ad->channels;
+		int byte_size = ad->buffer_size * sizeof(int16_t);
 		if (pa_simple_write(ad->pulse, ad->samples_out, byte_size, &error_code) < 0) {
 		if (pa_simple_write(ad->pulse, ad->samples_out, byte_size, &error_code) < 0) {
 			// can't recover here
 			// can't recover here
 			fprintf(stderr, "PulseAudio failed and can't recover: %s\n", pa_strerror(error_code));
 			fprintf(stderr, "PulseAudio failed and can't recover: %s\n", pa_strerror(error_code));
@@ -175,13 +181,20 @@ void AudioDriverPulseAudio::finish() {
 	exit_thread = true;
 	exit_thread = true;
 	Thread::wait_to_finish(thread);
 	Thread::wait_to_finish(thread);
 
 
-	if (pulse)
+	if (pulse) {
 		pa_simple_free(pulse);
 		pa_simple_free(pulse);
+		pulse = NULL;
+	}
 
 
 	if (samples_in) {
 	if (samples_in) {
 		memdelete_arr(samples_in);
 		memdelete_arr(samples_in);
+		samples_in = NULL;
+	}
+
+	if (samples_out) {
 		memdelete_arr(samples_out);
 		memdelete_arr(samples_out);
-	};
+		samples_out = NULL;
+	}
 
 
 	memdelete(thread);
 	memdelete(thread);
 	if (mutex) {
 	if (mutex) {
@@ -194,10 +207,15 @@ void AudioDriverPulseAudio::finish() {
 
 
 AudioDriverPulseAudio::AudioDriverPulseAudio() {
 AudioDriverPulseAudio::AudioDriverPulseAudio() {
 
 
+	samples_in = NULL;
+	samples_out = NULL;
 	mutex = NULL;
 	mutex = NULL;
 	thread = NULL;
 	thread = NULL;
 	pulse = NULL;
 	pulse = NULL;
 	latency = 0;
 	latency = 0;
+	buffer_frames = 0;
+	buffer_size = 0;
+	channels = 0;
 }
 }
 
 
 AudioDriverPulseAudio::~AudioDriverPulseAudio() {
 AudioDriverPulseAudio::~AudioDriverPulseAudio() {

+ 1 - 0
drivers/pulseaudio/audio_driver_pulseaudio.h

@@ -51,6 +51,7 @@ class AudioDriverPulseAudio : public AudioDriver {
 	unsigned int mix_rate;
 	unsigned int mix_rate;
 	SpeakerMode speaker_mode;
 	SpeakerMode speaker_mode;
 
 
+	unsigned int buffer_frames;
 	unsigned int buffer_size;
 	unsigned int buffer_size;
 	int channels;
 	int channels;
 
 

+ 6 - 7
drivers/rtaudio/audio_driver_rtaudio.cpp

@@ -107,14 +107,13 @@ Error AudioDriverRtAudio::init() {
 	options.numberOfBuffers = 4;
 	options.numberOfBuffers = 4;
 
 
 	parameters.firstChannel = 0;
 	parameters.firstChannel = 0;
-	mix_rate = GLOBAL_DEF("audio/mix_rate", 44100);
+	mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
 
 
-	int latency = GLOBAL_DEF("audio/output_latency", 25);
-	// calculate desired buffer_size
-	unsigned int buffer_size = closest_power_of_2(latency * mix_rate / 1000);
+	int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+	unsigned int buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
 
 
 	if (OS::get_singleton()->is_stdout_verbose()) {
 	if (OS::get_singleton()->is_stdout_verbose()) {
-		print_line("audio buffer size: " + itos(buffer_size));
+		print_line("audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
 	}
 	}
 
 
 	short int tries = 2;
 	short int tries = 2;
@@ -127,7 +126,7 @@ Error AudioDriverRtAudio::init() {
 		};
 		};
 
 
 		try {
 		try {
-			dac->openStream(&parameters, NULL, RTAUDIO_SINT32, mix_rate, &buffer_size, &callback, this, &options);
+			dac->openStream(&parameters, NULL, RTAUDIO_SINT32, mix_rate, &buffer_frames, &callback, this, &options);
 			active = true;
 			active = true;
 
 
 			break;
 			break;
@@ -199,7 +198,7 @@ AudioDriverRtAudio::AudioDriverRtAudio() {
 	active = false;
 	active = false;
 	mutex = NULL;
 	mutex = NULL;
 	dac = NULL;
 	dac = NULL;
-	mix_rate = 44100;
+	mix_rate = DEFAULT_MIX_RATE;
 	speaker_mode = SPEAKER_MODE_STEREO;
 	speaker_mode = SPEAKER_MODE_STEREO;
 }
 }
 
 

+ 23 - 10
drivers/wasapi/audio_driver_wasapi.cpp

@@ -65,6 +65,18 @@ Error AudioDriverWASAPI::init_device() {
 	format_tag = pwfex->wFormatTag;
 	format_tag = pwfex->wFormatTag;
 	bits_per_sample = pwfex->wBitsPerSample;
 	bits_per_sample = pwfex->wBitsPerSample;
 
 
+	switch (channels) {
+		case 2: // Stereo
+		case 6: // Surround 5.1
+		case 8: // Surround 7.1
+			break;
+
+		default:
+			ERR_PRINT("WASAPI: Unsupported number of channels");
+			ERR_FAIL_V(ERR_CANT_OPEN);
+			break;
+	}
+
 	if (format_tag == WAVE_FORMAT_EXTENSIBLE) {
 	if (format_tag == WAVE_FORMAT_EXTENSIBLE) {
 		WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)pwfex;
 		WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)pwfex;
 
 
@@ -83,13 +95,6 @@ Error AudioDriverWASAPI::init_device() {
 		}
 		}
 	}
 	}
 
 
-	int latency = GLOBAL_DEF("audio/output_latency", 25);
-	buffer_size = closest_power_of_2(latency * mix_rate / 1000);
-
-	if (OS::get_singleton()->is_stdout_verbose()) {
-		print_line("audio buffer size: " + itos(buffer_size));
-	}
-
 	hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 0, 0, pwfex, NULL);
 	hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 0, 0, pwfex, NULL);
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 
 
@@ -102,11 +107,20 @@ Error AudioDriverWASAPI::init_device() {
 	hr = audio_client->GetService(IID_IAudioRenderClient, (void **)&render_client);
 	hr = audio_client->GetService(IID_IAudioRenderClient, (void **)&render_client);
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 
 
+	UINT32 max_frames;
 	hr = audio_client->GetBufferSize(&max_frames);
 	hr = audio_client->GetBufferSize(&max_frames);
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 
 
+	// Due to WASAPI Shared Mode we have no control of the buffer size
+	buffer_frames = max_frames;
+
+	// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
+	buffer_size = buffer_frames * channels;
 	samples_in.resize(buffer_size);
 	samples_in.resize(buffer_size);
-	buffer_frames = buffer_size / channels;
+
+	if (OS::get_singleton()->is_stdout_verbose()) {
+		print_line("audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
+	}
 
 
 	return OK;
 	return OK;
 }
 }
@@ -200,7 +214,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
 			HRESULT hr = ad->audio_client->GetCurrentPadding(&cur_frames);
 			HRESULT hr = ad->audio_client->GetCurrentPadding(&cur_frames);
 			if (hr == S_OK) {
 			if (hr == S_OK) {
 				// Check how much frames are available on the WASAPI buffer
 				// Check how much frames are available on the WASAPI buffer
-				UINT32 avail_frames = ad->max_frames - cur_frames;
+				UINT32 avail_frames = ad->buffer_frames - cur_frames;
 				UINT32 write_frames = avail_frames > left_frames ? left_frames : avail_frames;
 				UINT32 write_frames = avail_frames > left_frames ? left_frames : avail_frames;
 
 
 				BYTE *buffer = NULL;
 				BYTE *buffer = NULL;
@@ -332,7 +346,6 @@ AudioDriverWASAPI::AudioDriverWASAPI() {
 	mutex = NULL;
 	mutex = NULL;
 	thread = NULL;
 	thread = NULL;
 
 
-	max_frames = 0;
 	format_tag = 0;
 	format_tag = 0;
 	bits_per_sample = 0;
 	bits_per_sample = 0;
 
 

+ 0 - 1
drivers/wasapi/audio_driver_wasapi.h

@@ -48,7 +48,6 @@ class AudioDriverWASAPI : public AudioDriver {
 	Mutex *mutex;
 	Mutex *mutex;
 	Thread *thread;
 	Thread *thread;
 
 
-	UINT32 max_frames;
 	WORD format_tag;
 	WORD format_tag;
 	WORD bits_per_sample;
 	WORD bits_per_sample;
 
 

+ 17 - 9
platform/osx/audio_driver_osx.cpp

@@ -77,7 +77,7 @@ Error AudioDriverOSX::initDevice() {
 			break;
 			break;
 	}*/
 	}*/
 
 
-	mix_rate = GLOBAL_DEF("audio/mix_rate", 44100);
+	mix_rate = GLOBAL_DEF("audio/mix_rate", DEFAULT_MIX_RATE);
 
 
 	zeromem(&strdesc, sizeof(strdesc));
 	zeromem(&strdesc, sizeof(strdesc));
 	strdesc.mFormatID = kAudioFormatLinearPCM;
 	strdesc.mFormatID = kAudioFormatLinearPCM;
@@ -92,15 +92,19 @@ Error AudioDriverOSX::initDevice() {
 	result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc));
 	result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc));
 	ERR_FAIL_COND_V(result != noErr, FAILED);
 	ERR_FAIL_COND_V(result != noErr, FAILED);
 
 
-	int latency = GLOBAL_DEF("audio/output_latency", 25);
-	unsigned int buffer_size = closest_power_of_2(latency * mix_rate / 1000);
+	int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+	// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
+	buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
 
 
-	if (OS::get_singleton()->is_stdout_verbose()) {
-		print_line("audio buffer size: " + itos(buffer_size) + " calculated latency: " + itos(buffer_size * 1000 / mix_rate));
-	}
+	result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, kOutputBus, &buffer_frames, sizeof(UInt32));
+	ERR_FAIL_COND_V(result != noErr, FAILED);
 
 
+	buffer_size = buffer_frames * channels;
 	samples_in.resize(buffer_size);
 	samples_in.resize(buffer_size);
-	buffer_frames = buffer_size / channels;
+
+	if (OS::get_singleton()->is_stdout_verbose()) {
+		print_line("audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms");
+	}
 
 
 	AURenderCallbackStruct callback;
 	AURenderCallbackStruct callback;
 	zeromem(&callback, sizeof(AURenderCallbackStruct));
 	zeromem(&callback, sizeof(AURenderCallbackStruct));
@@ -234,7 +238,7 @@ void AudioDriverOSX::start() {
 };
 };
 
 
 int AudioDriverOSX::get_mix_rate() const {
 int AudioDriverOSX::get_mix_rate() const {
-	return 44100;
+	return mix_rate;
 };
 };
 
 
 AudioDriver::SpeakerMode AudioDriverOSX::get_speaker_mode() const {
 AudioDriver::SpeakerMode AudioDriverOSX::get_speaker_mode() const {
@@ -282,8 +286,12 @@ AudioDriverOSX::AudioDriverOSX() {
 	active = false;
 	active = false;
 	mutex = NULL;
 	mutex = NULL;
 
 
-	mix_rate = 44100;
+	mix_rate = 0;
 	channels = 2;
 	channels = 2;
+
+	buffer_size = 0;
+	buffer_frames = 0;
+
 	samples_in.clear();
 	samples_in.clear();
 };
 };
 
 

+ 3 - 2
platform/osx/audio_driver_osx.h

@@ -45,8 +45,9 @@ class AudioDriverOSX : public AudioDriver {
 	Mutex *mutex;
 	Mutex *mutex;
 
 
 	int mix_rate;
 	int mix_rate;
-	int channels;
-	int buffer_frames;
+	unsigned int channels;
+	unsigned int buffer_frames;
+	unsigned int buffer_size;
 
 
 	Vector<int32_t> samples_in;
 	Vector<int32_t> samples_in;
 
 

+ 7 - 10
servers/audio/audio_driver_dummy.cpp

@@ -37,17 +37,16 @@ Error AudioDriverDummy::init() {
 	active = false;
 	active = false;
 	thread_exited = false;
 	thread_exited = false;
 	exit_thread = false;
 	exit_thread = false;
-	pcm_open = false;
 	samples_in = NULL;
 	samples_in = NULL;
 
 
-	mix_rate = 44100;
+	mix_rate = DEFAULT_MIX_RATE;
 	speaker_mode = SPEAKER_MODE_STEREO;
 	speaker_mode = SPEAKER_MODE_STEREO;
 	channels = 2;
 	channels = 2;
 
 
-	int latency = GLOBAL_DEF("audio/output_latency", 25);
-	buffer_size = next_power_of_2(latency * mix_rate / 1000);
+	int latency = GLOBAL_DEF("audio/output_latency", DEFAULT_OUTPUT_LATENCY);
+	buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
 
 
-	samples_in = memnew_arr(int32_t, buffer_size * channels);
+	samples_in = memnew_arr(int32_t, buffer_frames * channels);
 
 
 	mutex = Mutex::create();
 	mutex = Mutex::create();
 	thread = Thread::create(AudioDriverDummy::thread_func, this);
 	thread = Thread::create(AudioDriverDummy::thread_func, this);
@@ -59,17 +58,15 @@ void AudioDriverDummy::thread_func(void *p_udata) {
 
 
 	AudioDriverDummy *ad = (AudioDriverDummy *)p_udata;
 	AudioDriverDummy *ad = (AudioDriverDummy *)p_udata;
 
 
-	uint64_t usdelay = (ad->buffer_size / float(ad->mix_rate)) * 1000000;
+	uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000;
 
 
 	while (!ad->exit_thread) {
 	while (!ad->exit_thread) {
 
 
-		if (!ad->active) {
-
-		} else {
+		if (ad->active) {
 
 
 			ad->lock();
 			ad->lock();
 
 
-			ad->audio_server_process(ad->buffer_size, ad->samples_in);
+			ad->audio_server_process(ad->buffer_frames, ad->samples_in);
 
 
 			ad->unlock();
 			ad->unlock();
 		};
 		};

+ 1 - 2
servers/audio/audio_driver_dummy.h

@@ -43,8 +43,8 @@ class AudioDriverDummy : public AudioDriver {
 	int32_t *samples_in;
 	int32_t *samples_in;
 
 
 	static void thread_func(void *p_udata);
 	static void thread_func(void *p_udata);
-	int buffer_size;
 
 
+	unsigned int buffer_frames;
 	unsigned int mix_rate;
 	unsigned int mix_rate;
 	SpeakerMode speaker_mode;
 	SpeakerMode speaker_mode;
 
 
@@ -53,7 +53,6 @@ class AudioDriverDummy : public AudioDriver {
 	bool active;
 	bool active;
 	bool thread_exited;
 	bool thread_exited;
 	mutable bool exit_thread;
 	mutable bool exit_thread;
-	bool pcm_open;
 
 
 public:
 public:
 	const char *get_name() const {
 	const char *get_name() const {

+ 23 - 0
servers/audio_server.cpp

@@ -155,6 +155,29 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
 		todo -= to_copy;
 		todo -= to_copy;
 		to_mix -= to_copy;
 		to_mix -= to_copy;
 	}
 	}
+
+#ifdef DEBUG_ENABLED
+	if (OS::get_singleton() && OS::get_singleton()->is_stdout_verbose()) {
+		static uint64_t first_ticks = 0;
+		static uint64_t last_ticks = 0;
+		static uint64_t ticks = 0;
+		static int count = 0;
+		static int total = 0;
+
+		ticks = OS::get_singleton()->get_ticks_msec();
+		if ((ticks - first_ticks) > 10 * 1000) {
+			print_line("Audio Driver " + String(AudioDriver::get_singleton()->get_name()) + " average latency: " + itos(total / count) + "ms (frame=" + itos(p_frames) + ")");
+			first_ticks = ticks;
+			total = 0;
+			count = 0;
+		}
+
+		total += ticks - last_ticks;
+		count++;
+
+		last_ticks = ticks;
+	}
+#endif
 }
 }
 
 
 void AudioServer::_mix_step() {
 void AudioServer::_mix_step() {

+ 3 - 0
servers/audio_server.h

@@ -54,6 +54,9 @@ public:
 		SPEAKER_SURROUND_71,
 		SPEAKER_SURROUND_71,
 	};
 	};
 
 
+	static const int DEFAULT_MIX_RATE = 44100;
+	static const int DEFAULT_OUTPUT_LATENCY = 15;
+
 	static AudioDriver *get_singleton();
 	static AudioDriver *get_singleton();
 	void set_singleton();
 	void set_singleton();