summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp19
-rw-r--r--drivers/alsa/audio_driver_alsa.h1
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp44
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.h1
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp13
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp33
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h1
7 files changed, 75 insertions, 37 deletions
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 40c66b0bc5..216100bac6 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -31,6 +31,7 @@
#ifdef ALSA_ENABLED
+#include "os/os.h"
#include "project_settings.h"
#include <errno.h>
@@ -44,7 +45,7 @@ Error AudioDriverALSA::init() {
samples_in = 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;
channels = 2;
@@ -86,19 +87,25 @@ Error AudioDriverALSA::init() {
status = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &mix_rate, NULL);
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
status = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size);
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);
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);
CHECK_FAIL(status < 0);
diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h
index 83601be41b..c76ec0da61 100644
--- a/drivers/alsa/audio_driver_alsa.h
+++ b/drivers/alsa/audio_driver_alsa.h
@@ -51,6 +51,7 @@ class AudioDriverALSA : public AudioDriver {
unsigned int mix_rate;
SpeakerMode speaker_mode;
+ snd_pcm_uframes_t buffer_frames;
snd_pcm_uframes_t buffer_size;
snd_pcm_uframes_t period_size;
int channels;
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 356b1ad958..1798c84d85 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -33,6 +33,7 @@
#include <pulse/error.h>
+#include "os/os.h"
#include "project_settings.h"
Error AudioDriverPulseAudio::init() {
@@ -44,7 +45,7 @@ Error AudioDriverPulseAudio::init() {
samples_in = 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;
channels = 2;
@@ -53,12 +54,17 @@ Error AudioDriverPulseAudio::init() {
spec.channels = channels;
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;
- // 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
attr.prebuf = (uint32_t)-1;
attr.maxlength = (uint32_t)-1;
@@ -80,8 +86,8 @@ Error AudioDriverPulseAudio::init() {
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();
thread = Thread::create(AudioDriverPulseAudio::thread_func, this);
@@ -106,18 +112,18 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
while (!ad->exit_thread) {
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;
}
} else {
ad->lock();
- ad->audio_server_process(ad->buffer_size, ad->samples_in);
+ ad->audio_server_process(ad->buffer_frames, ad->samples_in);
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;
}
}
@@ -125,7 +131,7 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
// pa_simple_write always consumes the entire buffer
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) {
// can't recover here
fprintf(stderr, "PulseAudio failed and can't recover: %s\n", pa_strerror(error_code));
@@ -175,13 +181,20 @@ void AudioDriverPulseAudio::finish() {
exit_thread = true;
Thread::wait_to_finish(thread);
- if (pulse)
+ if (pulse) {
pa_simple_free(pulse);
+ pulse = NULL;
+ }
if (samples_in) {
memdelete_arr(samples_in);
+ samples_in = NULL;
+ }
+
+ if (samples_out) {
memdelete_arr(samples_out);
- };
+ samples_out = NULL;
+ }
memdelete(thread);
if (mutex) {
@@ -194,10 +207,15 @@ void AudioDriverPulseAudio::finish() {
AudioDriverPulseAudio::AudioDriverPulseAudio() {
+ samples_in = NULL;
+ samples_out = NULL;
mutex = NULL;
thread = NULL;
pulse = NULL;
latency = 0;
+ buffer_frames = 0;
+ buffer_size = 0;
+ channels = 0;
}
AudioDriverPulseAudio::~AudioDriverPulseAudio() {
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h
index 2f56726617..9ae0b7e50c 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.h
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.h
@@ -51,6 +51,7 @@ class AudioDriverPulseAudio : public AudioDriver {
unsigned int mix_rate;
SpeakerMode speaker_mode;
+ unsigned int buffer_frames;
unsigned int buffer_size;
int channels;
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index 7de3ff192e..ae5fdd28b6 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -107,14 +107,13 @@ Error AudioDriverRtAudio::init() {
options.numberOfBuffers = 4;
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()) {
- 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;
@@ -127,7 +126,7 @@ Error AudioDriverRtAudio::init() {
};
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;
break;
@@ -199,7 +198,7 @@ AudioDriverRtAudio::AudioDriverRtAudio() {
active = false;
mutex = NULL;
dac = NULL;
- mix_rate = 44100;
+ mix_rate = DEFAULT_MIX_RATE;
speaker_mode = SPEAKER_MODE_STEREO;
}
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index 6e01b5f524..4c1f90ec24 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -65,6 +65,18 @@ Error AudioDriverWASAPI::init_device() {
format_tag = pwfex->wFormatTag;
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) {
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);
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);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
+ UINT32 max_frames;
hr = audio_client->GetBufferSize(&max_frames);
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);
- 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;
}
@@ -200,7 +214,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
HRESULT hr = ad->audio_client->GetCurrentPadding(&cur_frames);
if (hr == S_OK) {
// 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;
BYTE *buffer = NULL;
@@ -332,7 +346,6 @@ AudioDriverWASAPI::AudioDriverWASAPI() {
mutex = NULL;
thread = NULL;
- max_frames = 0;
format_tag = 0;
bits_per_sample = 0;
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index b91751f87e..d1d3663fe5 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -48,7 +48,6 @@ class AudioDriverWASAPI : public AudioDriver {
Mutex *mutex;
Thread *thread;
- UINT32 max_frames;
WORD format_tag;
WORD bits_per_sample;