Browse Source

Fixed audio clipping on WASAPI by fixing argument order on AudioClient
Initialize method ensuring a larger capture buffer and adding bounds
to the capture and stream.

Saracen 7 years ago
parent
commit
aca6e291d6
3 changed files with 34 additions and 14 deletions
  1. 10 4
      drivers/wasapi/audio_driver_wasapi.cpp
  2. 22 10
      servers/audio/audio_stream.cpp
  3. 2 0
      servers/audio_server.h

+ 10 - 4
drivers/wasapi/audio_driver_wasapi.cpp

@@ -65,6 +65,8 @@ const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
 #define REFTIMES_PER_SEC 10000000
 #define REFTIMES_PER_MILLISEC 10000
 
+#define CAPTURE_BUFFER_CHANNELS 2
+
 static StringName capture_device_id;
 static bool default_render_device_changed = false;
 static bool default_capture_device_changed = false;
@@ -271,7 +273,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c
 		pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8);
 	}
 
-	hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, 0, p_capture ? REFTIMES_PER_SEC : 0, pwfex, NULL);
+	hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_capture ? REFTIMES_PER_SEC : 0, 0, pwfex, NULL);
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 
 	if (p_capture) {
@@ -338,11 +340,12 @@ Error AudioDriverWASAPI::init_capture_device(bool reinit) {
 	ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
 
 	// Set the buffer size
-	audio_input_buffer.resize(max_frames * 8);
+	audio_input_buffer.resize(max_frames * CAPTURE_BUFFER_CHANNELS);
 	for (int i = 0; i < audio_input_buffer.size(); i++) {
 		audio_input_buffer.write[i] = 0;
 	}
 	audio_input_position = 0;
+	audio_input_size = 0;
 
 	return OK;
 }
@@ -676,7 +679,7 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
 
 					// fixme: Only works for floating point atm
 					for (int j = 0; j < num_frames_available; j++) {
-						int32_t sample_channel[2];
+						int32_t sample_channel[CAPTURE_BUFFER_CHANNELS];
 
 						if (flags & AUDCLNT_BUFFERFLAGS_SILENT) {
 							sample_channel[0] = sample_channel[1] = 0;
@@ -692,11 +695,14 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
 							}
 						}
 
-						for (int k = 0; k < 2; k++) {
+						for (int k = 0; k < CAPTURE_BUFFER_CHANNELS; k++) {
 							ad->audio_input_buffer.write[ad->audio_input_position++] = sample_channel[k];
 							if (ad->audio_input_position >= ad->audio_input_buffer.size()) {
 								ad->audio_input_position = 0;
 							}
+							if (ad->audio_input_size < ad->audio_input_buffer.size()) {
+								ad->audio_input_size++;
+							}
 						}
 					}
 

+ 22 - 10
servers/audio/audio_stream.cpp

@@ -135,19 +135,31 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
 	AudioDriver::get_singleton()->lock();
 
 	Vector<int32_t> buf = AudioDriver::get_singleton()->get_audio_input_buffer();
+	unsigned int audio_input_size = AudioDriver::get_singleton()->get_audio_input_size();
 
-	for (int i = 0; i < p_frames; i++) {
-
-		float l = (buf[input_ofs++] >> 16) / 32768.f;
-		if (input_ofs >= buf.size()) {
-			input_ofs = 0;
-		}
-		float r = (buf[input_ofs++] >> 16) / 32768.f;
-		if (input_ofs >= buf.size()) {
-			input_ofs = 0;
+	// p_frames is multipled by two since an AudioFrame is stereo
+	if ((p_frames * 2) > audio_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 (audio_input_size >= input_ofs) {
+				float l = (buf[input_ofs++] >> 16) / 32768.f;
+				if (input_ofs >= buf.size()) {
+					input_ofs = 0;
+				}
+				float r = (buf[input_ofs++] >> 16) / 32768.f;
+				if (input_ofs >= buf.size()) {
+					input_ofs = 0;
+				}
 
-		p_buffer[i] = AudioFrame(l, r);
+				p_buffer[i] = AudioFrame(l, r);
+			} else {
+				p_buffer[i] = AudioFrame(0.0f, 0.0f);
+			}
+		}
 	}
 
 	AudioDriver::get_singleton()->unlock();

+ 2 - 0
servers/audio_server.h

@@ -55,6 +55,7 @@ class AudioDriver {
 protected:
 	Vector<int32_t> audio_input_buffer;
 	unsigned int audio_input_position;
+	unsigned int audio_input_size;
 
 	void audio_server_process(int p_frames, int32_t *p_buffer, bool p_update_mix_time = true);
 	void update_mix_time(int p_frames);
@@ -109,6 +110,7 @@ public:
 
 	Vector<int32_t> get_audio_input_buffer() { return audio_input_buffer; }
 	unsigned int get_audio_input_position() { return audio_input_position; }
+	unsigned int get_audio_input_size() { return audio_input_size; }
 
 #ifdef DEBUG_ENABLED
 	uint64_t get_profiling_time() const { return prof_time; }