diff --git a/src/apu.rs b/src/apu.rs
index 77a24ef925c7f379a54e5650e71ef14b923701d8..229eb4084845176b9351014060e4562a50531a3e 100644
--- a/src/apu.rs
+++ b/src/apu.rs
@@ -9,6 +9,8 @@ const DUTY_TABLE: [[u8; 8]; 4] = [
     [0, 1, 1, 1, 1, 1, 1, 0],
 ];
 
+const CH4_DIVISORS: [u8; 8] = [8, 16, 32, 48, 64, 80, 96, 112];
+
 pub enum Channel {
     Ch1,
     Ch2,
@@ -60,13 +62,18 @@ pub struct Apu {
     ch3_enabled: bool,
 
     ch4_timer: i16,
+    ch4_envelope_sequence: u8,
+    ch4_envelope_enabled: bool,
     ch4_output: u8,
     ch4_length_timer: u8,
     ch4_pace: u8,
     ch4_direction: u8,
     ch4_volume: u8,
     ch4_output_level: u8,
-    ch4_wave_length: u16,
+    ch4_divisor: u8,
+    ch4_width_mode: bool,
+    ch4_clock_shift: u8,
+    ch4_lfsr: u16,
     ch4_length_stop: bool,
     ch4_enabled: bool,
 
@@ -129,13 +136,18 @@ impl Apu {
             ch3_enabled: false,
 
             ch4_timer: 0,
+            ch4_envelope_sequence: 0,
+            ch4_envelope_enabled: false,
             ch4_output: 0,
             ch4_length_timer: 0x0,
             ch4_pace: 0x0,
             ch4_direction: 0x0,
             ch4_volume: 0x0,
             ch4_output_level: 0x0,
-            ch4_wave_length: 0x0,
+            ch4_divisor: 0x0,
+            ch4_width_mode: false,
+            ch4_clock_shift: 0x0,
+            ch4_lfsr: 0x0,
             ch4_length_stop: false,
             ch4_enabled: false,
 
@@ -208,10 +220,18 @@ impl Apu {
         self.ch3_enabled = false;
 
         self.ch4_timer = 0;
+        self.ch4_envelope_sequence = 0;
+        self.ch4_envelope_enabled = false;
         self.ch4_output = 0;
         self.ch4_length_timer = 0x0;
+        self.ch4_pace = 0x0;
+        self.ch4_direction = 0x0;
+        self.ch4_volume = 0x0;
         self.ch4_output_level = 0x0;
-        self.ch4_wave_length = 0x0;
+        self.ch4_divisor = 0x0;
+        self.ch4_width_mode = false;
+        self.ch4_clock_shift = 0x0;
+        self.ch4_lfsr = 0x0;
         self.ch4_length_stop = false;
         self.ch4_enabled = false;
 
@@ -278,7 +298,8 @@ impl Apu {
             }
 
             // @TODO the CPU clock is hardcoded here, we must handle situations
-            // where there's some kind of overclock
+            // where there's some kind of overclock, and for that to happen the
+            // current CPU clock must be propagated here
             self.output_timer += (4194304.0 / self.sampling_rate as f32) as i16;
         }
     }
@@ -383,12 +404,19 @@ impl Apu {
             }
             // 0xFF22 — NR43: Channel 4 frequency & randomness
             0xff22 => {
-                //@TODO need to implement this one!
+                self.ch4_divisor = value & 0x07;
+                self.ch4_width_mode = value & 0x08 == 0x08;
+                self.ch4_clock_shift = (value & 0xf0) >> 4;
             }
             // 0xFF23 — NR44: Channel 4 control
             0xff23 => {
                 self.ch4_length_stop |= value & 0x40 == 0x40;
                 self.ch4_enabled |= value & 0x80 == 0x80;
+                if value & 0x80 == 0x80 {
+                    self.ch4_timer =
+                        (CH4_DIVISORS[self.ch4_divisor as usize] << self.ch4_clock_shift) as i16;
+                    self.ch4_lfsr = 0x7ff1;
+                }
             }
 
             // 0xFF30-0xFF3F — Wave pattern RAM
@@ -416,6 +444,10 @@ impl Apu {
         self.ch3_output
     }
 
+    pub fn ch4_output(&self) -> u8 {
+        self.ch4_output
+    }
+
     pub fn audio_buffer(&self) -> &VecDeque<u8> {
         &self.audio_buffer
     }
@@ -463,7 +495,13 @@ impl Apu {
                     self.ch3_length_timer = 0;
                 }
             }
-            Channel::Ch4 => (),
+            Channel::Ch4 => {
+                self.ch4_length_timer = self.ch4_length_timer.saturating_add(1);
+                if self.ch4_length_timer >= 64 {
+                    self.ch4_enabled = !self.ch4_length_stop;
+                    self.ch4_length_timer = 0;
+                }
+            }
         }
     }
 
@@ -510,7 +548,23 @@ impl Apu {
                 }
             }
             Channel::Ch3 => (),
-            Channel::Ch4 => (),
+            Channel::Ch4 => {
+                if !self.ch4_enabled || !self.ch4_envelope_enabled {
+                    return;
+                }
+                self.ch4_envelope_sequence += 1;
+                if self.ch4_envelope_sequence >= self.ch4_pace {
+                    if self.ch4_direction == 0x01 {
+                        self.ch4_volume = self.ch4_volume.saturating_add(1);
+                    } else {
+                        self.ch4_volume = self.ch4_volume.saturating_sub(1);
+                    }
+                    if self.ch4_volume == 0 || self.ch4_volume == 15 {
+                        self.ch4_envelope_enabled = false;
+                    }
+                    self.ch4_envelope_sequence = 0;
+                }
+            }
         }
     }
 
@@ -541,6 +595,7 @@ impl Apu {
         self.tick_ch1(cycles);
         self.tick_ch2(cycles);
         self.tick_ch3(cycles);
+        self.tick_ch4(cycles);
     }
 
     #[inline(always)]
@@ -615,6 +670,38 @@ impl Apu {
         self.ch3_timer += ((2048 - self.ch3_wave_length) << 1) as i16;
         self.ch3_position = (self.ch3_position + 1) & 31;
     }
+
+    #[inline(always)]
+    fn tick_ch4(&mut self, cycles: u8) {
+        self.ch4_timer = self.ch4_timer.saturating_sub(cycles as i16);
+        if self.ch4_timer > 0 {
+            return;
+        }
+
+        if self.ch4_enabled {
+            // obtains the current value of the LFSR based as
+            // the XOR of the 1st and 2nd bit of the LFSR
+            let result = ((self.ch4_lfsr & 0x0001) ^ ((self.ch4_lfsr >> 1) & 0x0001)) == 0x0001;
+
+            // shifts the LFSR to the right and in case the
+            // value is positive sets the 15th bit to 1
+            self.ch4_lfsr >>= 1;
+            self.ch4_lfsr |= if result { 0x0001 << 14 } else { 0x0 };
+
+            // in case the short width mode (7 bits) is set then
+            // the 6th bit will be set to value of the 15th bit
+            if self.ch4_width_mode {
+                self.ch4_lfsr &= 0xbf;
+                self.ch4_lfsr |= if result { 0x40 } else { 0x00 };
+            }
+
+            self.ch4_output = if result { self.ch4_volume } else { 0 };
+        } else {
+            self.ch4_output = 0;
+        }
+
+        self.ch4_timer += (CH4_DIVISORS[self.ch4_divisor as usize] << self.ch4_clock_shift) as i16;
+    }
 }
 
 impl Default for Apu {