mirror of
https://github.com/godotengine/godot
synced 2024-09-05 12:28:27 +00:00
Fix possible audio input buffer issues
This commit is contained in:
parent
cf7a66195f
commit
fa26a5511d
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue