diff --git a/docs/badge/firmware-development.rst b/docs/badge/firmware-development.rst
index 65579de0eede0d11049c08ea03ebbb9a45bdae2c..f3338b31e5e9ae525c45e28074c82afa7fce21ae 100644
--- a/docs/badge/firmware-development.rst
+++ b/docs/badge/firmware-development.rst
@@ -53,7 +53,7 @@ For running the simulator, you'll need Python 3 with pygame and wasmer:
 ::
 
 	$ python3 -m venv venv
-	$ venv/bin/pip install pygame requests
+	$ venv/bin/pip install pygame requests pymad
         $ venv/bin/pip install wasmer wasmer-compiler-cranelift
 
 .. warning::
diff --git a/docs/badge/programming.rst b/docs/badge/programming.rst
index adccc6366f160244ca78ea70116ca8afcb341ef1..d504edcf1528d3c536f4d7595b2096ac63739e32 100644
--- a/docs/badge/programming.rst
+++ b/docs/badge/programming.rst
@@ -746,7 +746,7 @@ environment with the required packages:
     $ git clone https://git.flow3r.garden/flow3r/flow3r-firmware
     $ cd flow3r-firmware
     $ python3 -m venv venv
-    $ venv/bin/pip install pygame requests
+    $ venv/bin/pip install pygame requests pymad
     $ venv/bin/pip install wasmer wasmer-compiler-cranelift
 
 .. warning::
diff --git a/sim/fakes/media.py b/sim/fakes/media.py
index 60bf2d0827b7794e33d04bfb5e1235f283ad0bb8..4e2eb625e9d495a88a2e0c4f1ca6da57cadc6704 100644
--- a/sim/fakes/media.py
+++ b/sim/fakes/media.py
@@ -1,7 +1,13 @@
 import pygame
 from _sim import path_replace
 
+try:
+    import mad
+except ImportError:
+    mad = None
+
 _loaded = False
+_duration = 0
 
 
 def stop():
@@ -18,11 +24,13 @@ def load(path, paused=False):
     """
     Load path
     """
-    global _loaded
+    global _loaded, _duration
     if path.startswith(("http://", "https://")):
         return
     pygame.mixer.music.load(path_replace(path))
     pygame.mixer.music.play()
+    if mad:
+        _duration = mad.MadFile(path_replace(path)).total_time()
     if paused:
         pygame.mixer.music.pause()
     _loaded = True
@@ -90,10 +98,14 @@ def seek(pos):
         return
     pygame.mixer.music.play()
     pygame.mixer.music.rewind()
+    if mad:
+        pygame.mixer.music.set_pos(pos * get_duration())
 
 
 def get_duration():
-    return 99999
+    if not mad:
+        return 99999
+    return _duration / 1000
 
 
 def is_visual():
diff --git a/sim/requirements.txt b/sim/requirements.txt
index 42e7cd3c2d45a0c1bec60289f1cefa8ac9269dbd..c82ae356d0f03d2e8ddb6c99ad2682c44b5eb22c 100644
--- a/sim/requirements.txt
+++ b/sim/requirements.txt
@@ -1,4 +1,5 @@
 pygame
 requests
+pymad
 wasmer
 wasmer-compiler-cranelift
diff --git a/sim/run.py b/sim/run.py
index b79533699b5f377eed94fbf6e007bc31e336a333..6fb50ea142c1cec6eda00a6adb31217e992b36ef 100755
--- a/sim/run.py
+++ b/sim/run.py
@@ -29,6 +29,10 @@ try:
 except ImportError:
     print("Warning: `requests` is missing so no `urequests` mock will exist")
 
+try:
+    import mad
+except ImportError:
+    print("Warning: `mad` is missing, MP3 support in `media` mock will be limited")
 
 sys_path_orig = sys.path