diff --git a/src/libsuperderpy.c b/src/libsuperderpy.c
index aff4cc0..b1fa6d3 100644
--- a/src/libsuperderpy.c
+++ b/src/libsuperderpy.c
@@ -481,7 +481,7 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
 	al_destroy_mixer(game->audio.music);
 	al_destroy_mixer(game->audio.voice);
 	al_destroy_mixer(game->audio.mixer);
-	al_destroy_voice(game->audio.v); // FIXME: doesn't seem to work in Chromium under Emscripten
+	al_destroy_voice(game->audio.v);
 	al_destroy_cond(game->_priv.texture_sync_cond);
 	al_destroy_mutex(game->_priv.texture_sync_mutex);
 	al_destroy_cond(game->_priv.bsod_cond);
diff --git a/src/mainloop.c b/src/mainloop.c
index 874ac2a..47330cb 100644
--- a/src/mainloop.c
+++ b/src/mainloop.c
@@ -267,14 +267,23 @@ static inline bool MainloopTick(struct Game* game) {
 
 	while (tmp) {
 		if (tmp->pending_unload) {
+#ifdef __EMSCRIPTEN__
+			al_detach_voice(game->audio.v);
+#endif
 			PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
 			tmp->loaded = false;
 			tmp->pending_unload = false;
 			game->_priv.current_gamestate = tmp;
 			(*tmp->api->unload)(game, tmp->data);
 			PrintConsole(game, "Gamestate \"%s\" unloaded successfully.", tmp->name);
+#ifdef __EMSCRIPTEN__
+			al_attach_mixer_to_voice(game->audio.mixer, game->audio.v);
+#endif
 		}
 		if (tmp->pending_load) {
+#ifdef __EMSCRIPTEN__
+			al_detach_voice(game->audio.v);
+#endif
 			if (tmp->show_loading) {
 				(*game->_priv.loading.gamestate->api->start)(game, game->_priv.loading.gamestate->data);
 			}
@@ -371,6 +380,9 @@ static inline bool MainloopTick(struct Game* game) {
 			}
 			tmp->show_loading = true;
 			game->_priv.timestamp = al_get_time();
+#ifdef __EMSCRIPTEN__
+			al_attach_mixer_to_voice(game->audio.mixer, game->audio.v);
+#endif
 		}
 
 		tmp = tmp->next;