diff --git a/aegisub/src/audio_provider.cpp b/aegisub/src/audio_provider.cpp
index 1482a56d6124fd4ac0f7b8ec482a10cf78adffb8..9fb06e715588c092032fb11cfca14547c0142701 100644
--- a/aegisub/src/audio_provider.cpp
+++ b/aegisub/src/audio_provider.cpp
@@ -80,56 +80,45 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count,
 	}
 }
 
+void AudioProvider::ZeroFill(void *buf, int64_t count) const {
+	if (bytes_per_sample == 1)
+		// 8 bit formats are usually unsigned with bias 127
+		memset(buf, 127, count * channels);
+	else
+		// While everything else is signed
+		memset(buf, 0, count * bytes_per_sample * channels);
+}
+
 void AudioProvider::GetAudio(void *buf, int64_t start, int64_t count) const {
-	if (start+count > num_samples) {
-		int64_t oldcount = count;
-		count = num_samples-start;
-		if (count < 0) count = 0;
-
-		// Fill beyond with zero
-		if (bytes_per_sample == 1) {
-			char *temp = (char *) buf;
-			for (int i=count;i<oldcount;i++) {
-				temp[i] = 0;
-			}
-		}
-		if (bytes_per_sample == 2) {
-			short *temp = (short *) buf;
-			for (int i=count;i<oldcount;i++) {
-				temp[i] = 0;
-			}
-		}
+	if (start < 0) {
+		ZeroFill(buf, std::min(-start, count));
+		buf = static_cast<char *>(buf) + -start * bytes_per_sample * channels;
+		count += start;
+		start = 0;
 	}
 
 	if (start + count > num_samples) {
 		int64_t zero_count = std::min(count, start + count - num_samples);
 		count -= zero_count;
-		char *zero_buf = static_cast<char *>(buf) + count * bytes_per_sample * channels;
-
-		if (bytes_per_sample == 1)
-			// 8 bit formats are usually unsigned with bias 127
-			memset(zero_buf, 127, zero_count * channels);
-		else
-			// While everything else is signed
-			memset(zero_buf, 0, zero_count * bytes_per_sample * channels);
+		ZeroFill(static_cast<char *>(buf) + count * bytes_per_sample * channels, zero_count);
 	}
 
-	if (count > 0) {
-		try {
-			FillBuffer(buf, start, count);
-		}
-		catch (AudioDecodeError const& e) {
-			LOG_E("audio_provider") << e.GetChainedMessage();
-			memset(buf, 0, count*bytes_per_sample);
-			return;
-		}
-		catch (...) {
-			// FIXME: Poor error handling though better than none, to patch issue #800.
-			// Just return blank audio if real provider fails.
-			LOG_E("audio_provider") << "Unknown audio decoding error";
-			memset(buf, 0, count*bytes_per_sample);
-			return;
-		}
+	if (count <= 0) return;
+
+	try {
+		FillBuffer(buf, start, count);
+	}
+	catch (AudioDecodeError const& e) {
+		LOG_E("audio_provider") << e.GetChainedMessage();
+		ZeroFill(buf, count);
+		return;
+	}
+	catch (...) {
+		// FIXME: Poor error handling though better than none, to patch issue #800.
+		// Just return blank audio if real provider fails.
+		LOG_E("audio_provider") << "Unknown audio decoding error";
+		ZeroFill(buf, count);
+		return;
 	}
 }
 
diff --git a/aegisub/src/include/aegisub/audio_provider.h b/aegisub/src/include/aegisub/audio_provider.h
index fa7e6719166a5c276a8178bb2abbcac1fb8d615a..e029c6620359aed1a91c670528d839b00c53e2aa 100644
--- a/aegisub/src/include/aegisub/audio_provider.h
+++ b/aegisub/src/include/aegisub/audio_provider.h
@@ -69,6 +69,8 @@ protected:
 
 	virtual void FillBuffer(void *buf, int64_t start, int64_t count) const = 0;
 
+	void ZeroFill(void *buf, int64_t count) const;
+
 public:
 	virtual ~AudioProvider() { }