diff --git a/Machines/Apple/AppleIIgs/Sound.cpp b/Machines/Apple/AppleIIgs/Sound.cpp
index cdd92e13b..682954e10 100644
--- a/Machines/Apple/AppleIIgs/Sound.cpp
+++ b/Machines/Apple/AppleIIgs/Sound.cpp
@@ -174,6 +174,27 @@ uint8_t GLU::get_address_high() {
 
 // MARK: - Update logic.
 
+void GLU::skip_audio(EnsoniqState &state, size_t number_of_samples) {
+	// Just advance all oscillator pointers and check for interrupts.
+	// If a read occurs to the current-output level, generate it then.
+
+	for(int c = 0; c < local_.oscillator_count; c++) {
+		// Don't do anything for halted oscillators.
+		if(state.oscillators[c].control&1) continue;
+
+		// Update phase.
+		state.oscillators[c].position += state.oscillators[c].velocity * number_of_samples;
+
+		// Check for stops, and any interrupts that therefore flow.
+		if((state.oscillators[c].control & 1) && (state.oscillators[c].position & state.oscillators[c].overflow_mask)) {
+			// Apply halt, set interrupt request flag.
+			state.oscillators[c].position = 0;
+			state.oscillators[c].control |= 1;
+			state.oscillators[c].interrupt_request = true;
+		}
+	}
+}
+
 void GLU::generate_audio(size_t number_of_samples, std::int16_t *target) {
 	auto next_store = pending_stores_[pending_store_read_].load(std::memory_order::memory_order_acquire);
 	uint8_t next_amplitude = 255;
@@ -291,11 +312,3 @@ int16_t GLU::EnsoniqState::Oscillator::output(uint8_t *ram) {
 	// Samples are unsigned 8-bit; do the proper work to make volume work correctly.
 	return int8_t(level ^ 128) * volume;
 }
-
-void GLU::skip_audio(EnsoniqState &state, size_t number_of_samples) {
-	(void)number_of_samples;
-	(void)state;
-
-	// Just advance all oscillator pointers and check for interrupts.
-	// If a read occurs to the current-output level, generate it then.
-}
diff --git a/Machines/Apple/AppleIIgs/Sound.hpp b/Machines/Apple/AppleIIgs/Sound.hpp
index ca3e91c13..7cf949f8d 100644
--- a/Machines/Apple/AppleIIgs/Sound.hpp
+++ b/Machines/Apple/AppleIIgs/Sound.hpp
@@ -77,14 +77,16 @@ class GLU: public Outputs::Speaker::SampleSource {
 				uint8_t table_size;
 
 				// Derived state.
-				uint32_t overflow_mask;	// If a non-zero bit gets anywhere into the overflow mask, this channel
-										// has wrapped around. It's a function of table_size.
+				uint32_t overflow_mask;			// If a non-zero bit gets anywhere into the overflow mask, this channel
+												// has wrapped around. It's a function of table_size.
+				bool interrupt_request = false;	// Will be non-zero if this channel would request an interrupt, were
+												// it currently enabled to do so.
 
 				uint8_t sample(uint8_t *ram);
 				int16_t output(uint8_t *ram);
 			} oscillators[32];
 
-			// TODO: do all of these need to be on the audio thread?
+			// Some of these aren't actually needed on both threads.
 			uint8_t control;
 			uint8_t interrupt_state;
 			int oscillator_count;