Fix possible audio input buffer issues

This commit is contained in:
Marcelo Fernandez 2018-10-19 16:32:03 -03:00
parent cf7a66195f
commit fa26a5511d
8 changed files with 33 additions and 23 deletions

View file

@ -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));

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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;

View file

@ -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;

View file

@ -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