diff options
Diffstat (limited to 'drivers/pulseaudio/audio_driver_pulseaudio.cpp')
-rw-r--r-- | drivers/pulseaudio/audio_driver_pulseaudio.cpp | 131 |
1 files changed, 66 insertions, 65 deletions
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index 954d2c20f2..3a1317cbf6 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,48 +36,56 @@ Error AudioDriverPulseAudio::init() { - active = false; - thread_exited = false; - exit_thread = false; + active = false; + thread_exited = false; + exit_thread = false; pcm_open = false; samples_in = NULL; samples_out = NULL; - mix_rate = 44100; + mix_rate = GLOBAL_DEF("audio/mix_rate",44100); output_format = OUTPUT_STEREO; channels = 2; - pa_sample_spec spec; - spec.format = PA_SAMPLE_S16LE; - spec.channels = channels; - spec.rate = mix_rate; - - int error_code; - pulse = pa_simple_new(NULL, // default server - "Godot", // application name - PA_STREAM_PLAYBACK, - NULL, // default device - "Sound", // stream description - &spec, - NULL, // use default channel map - NULL, // use default buffering attributes - &error_code - ); - - if (pulse == NULL) { - - fprintf(stderr, "PulseAudio ERR: %s\n", pa_strerror(error_code));\ - ERR_FAIL_COND_V(pulse == NULL, ERR_CANT_OPEN); - } + pa_sample_spec spec; + spec.format = PA_SAMPLE_S16LE; + spec.channels = channels; + spec.rate = mix_rate; + + int latency = GLOBAL_DEF("audio/output_latency", 25); + buffer_size = nearest_power_of_2(latency * mix_rate / 1000); + + pa_buffer_attr attr; + // set to appropriate buffer size from global settings + attr.tlength = buffer_size; + // set them to be automatically chosen + attr.prebuf = (uint32_t)-1; + attr.maxlength = (uint32_t)-1; + attr.minreq = (uint32_t)-1; + + int error_code; + pulse = pa_simple_new( NULL, // default server + "Godot", // application name + PA_STREAM_PLAYBACK, + NULL, // default device + "Sound", // stream description + &spec, + NULL, // use default channel map + &attr, // use buffering attributes from above + &error_code + ); + + if (pulse == NULL) { + fprintf(stderr, "PulseAudio ERR: %s\n", pa_strerror(error_code));\ + ERR_FAIL_COND_V(pulse == NULL, ERR_CANT_OPEN); + } - int latency = GLOBAL_DEF("audio/output_latency", 25); - buffer_size = nearest_power_of_2(latency * mix_rate / 1000); - 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 * channels); + samples_out = memnew_arr(int16_t, buffer_size * channels); - mutex = Mutex::create(); - thread = Thread::create(AudioDriverPulseAudio::thread_func, this); + mutex = Mutex::create(); + thread = Thread::create(AudioDriverPulseAudio::thread_func, this); return OK; } @@ -95,47 +103,40 @@ float AudioDriverPulseAudio::get_latency() { void AudioDriverPulseAudio::thread_func(void* p_udata) { - AudioDriverPulseAudio* ad = (AudioDriverPulseAudio*)p_udata; + AudioDriverPulseAudio* ad = (AudioDriverPulseAudio*)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 * ad->channels; i++) { ad->samples_out[i] = 0; - } + } } else { - ad->lock(); ad->audio_server_process(ad->buffer_size, ad->samples_in); ad->unlock(); - for (unsigned int i=0; i < ad->buffer_size * ad->channels;i ++) { - - ad->samples_out[i] = ad->samples_in[i] >> 16; + for (unsigned int i=0; i < ad->buffer_size * ad->channels;i ++) { + ad->samples_out[i] = ad->samples_in[i] >> 16; } - } - - // pa_simple_write always consumes the entire buffer - - int error_code; - int byte_size = ad->buffer_size * sizeof(int16_t) * ad->channels; - 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)); - ad->active = false; - ad->exit_thread = true; - break; - } + // pa_simple_write always consumes the entire buffer - } - - ad->thread_exited = true; + int error_code; + int byte_size = ad->buffer_size * sizeof(int16_t) * ad->channels; + 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)); + ad->active = false; + ad->exit_thread = true; + break; + } + } + + ad->thread_exited = true; } void AudioDriverPulseAudio::start() { @@ -184,10 +185,10 @@ void AudioDriverPulseAudio::finish() { }; memdelete(thread); - if (mutex) { + if (mutex) { memdelete(mutex); - mutex = NULL; - } + mutex = NULL; + } thread = NULL; } @@ -195,9 +196,9 @@ void AudioDriverPulseAudio::finish() { AudioDriverPulseAudio::AudioDriverPulseAudio() { mutex = NULL; - thread = NULL; - pulse = NULL; - latency=0; + thread = NULL; + pulse = NULL; + latency=0; } AudioDriverPulseAudio::~AudioDriverPulseAudio() { |