diff --git a/code/daisy-looper/daisy-looper.ino b/code/daisy-looper/daisy-looper.ino
index cb83c8130892c9e383b9e2c9e6e2126c73cd0b59..3d48e15a26a412ac52cb65ed0f5170b4acc669d2 100644
--- a/code/daisy-looper/daisy-looper.ino
+++ b/code/daisy-looper/daisy-looper.ino
@@ -380,7 +380,7 @@ void loop() {
   // Delaytime is in samples
   if (!isnan(p5)) {  lfo_amount = p5; }
   if (!isnan(p6)) {  delaytime = 100.0f + p6 * 23900.0f; }
-  if (!isnan(p7)) {  reverbmix = p7; Serial.print("Reverb was not NaN: "); Serial.println(reverbmix); }
+  if (!isnan(p7)) {  reverbmix = p7; }
 
   // Render the UI (frame rate limited by UI_MAX_FPS in ui.h)
   // double start = millis();
diff --git a/code/daisy-looper/looper.h b/code/daisy-looper/looper.h
index 22a88047fc83eba6f37c201fe7d4699535090024..1914c7ffd984d64ebb4ff3cf229f931e1393d984 100644
--- a/code/daisy-looper/looper.h
+++ b/code/daisy-looper/looper.h
@@ -1,5 +1,6 @@
-#ifndef Looper_h
-#define Looper_h
+#pragma once
+
+#include "luts.h"
 
 namespace atoav {
 
@@ -17,267 +18,395 @@ enum RecStartMode {
   REC_START_MODE_LAST,
 };
 
-class Looper {
+enum PlaybackState {
+  PLAYBACK_STATE_STOPPED,
+  PLAYBACK_STATE_LOOP,
+  PLAYBACK_STATE_MULTILOOP,
+  PLAYBACK_STATE_MIDI,
+  PLAYBACK_STATE_LAST,
+};
+
+enum RecordingState {
+  REC_STATE_EMPTY,
+  REC_STATE_RECORDING,
+  REC_STATE_OVERDUBBING,
+  REC_STATE_ERASING,
+  REC_STATE_NONE,
+  REC_STATE_LAST,
+};
+
+// =================================================
+// =                   H E A D                     =
+// =================================================
+
+class Head {
   public:
-    void Init(float *buf, size_t length) {
-      buffer = buf;
-      buffer_length = length;
-      // Reset buffer contents to zero
-      memset(buffer, 0, sizeof(float) * buffer_length);
-    }
+    Head();
+    void activate();
+    void deactivate();
+    bool isActive();
+    void setPosition(float value);
+    void setIncrement(float value);
+    void incrementBy(float value);
+    void update();
+    float read();
+    float increment = 1.0f;
+  private:
+    bool active = true;
+    float position = 0.0f;
+};
 
+Head::Head() {
+
+}
+void Head::activate() {
+  this->active = true;
+}
+void Head::deactivate() {
+  this->active = false;
+}
+bool Head::isActive() {
+  return active;
+}
+void Head::setPosition(float value) {
+  this->position = value;
+}
+void Head::setIncrement(float value) {
+  this->increment = value;
+}
+void Head::incrementBy(float value) {
+  this->position += value;
+}
+void Head::update() {
+  this->position += this->increment;
+}
+float Head::read() {
+  return this->position;
+}
+
+
+// =================================================
+// =                 L O O P E R                   =
+// =================================================
+
+class Looper {
+	public:
+		Looper();
+    void Init(float *buf, size_t buf_size);
+    void SetRecord();
+    void SetOverdub();
+    void SetErase();
+    void SetStopWriting();
+    bool isWriting();
+    void ResetRecHead();
+    void SetLoop(float loop_start_time, float loop_length_time);
+    void Record(float in);
+    float Process();
+    float* getBuffer();
+    size_t getBufferLength();
+    void setRecPitchMode(RecPitchMode mode);
+    void setRecStartMode(RecStartMode mode);
+    float GetPlayhead();
+    float* GetPlayheads();
+    float GetRecHead();
+    bool toggleRecMode();
+    void setRecModeFull();
+    void setRecModeLoop();
+    void setRecModeFullShot();
+    void setRecModeLoopShot();
+    void setPlaybackSpeed(float increment);
+    void addToPlayhead(float value);
+    float loop_start_f = 0.0f;
+    float loop_length_f = 1.0f;
     RecPitchMode rec_pitch_mode = REC_PITCH_MODE_NORMAL;
     RecStartMode rec_start_mode = REC_START_MODE_BUFFER;
+    PlaybackState playback_state = PLAYBACK_STATE_LOOP;
+    RecordingState recording_state = REC_STATE_EMPTY;
 
-    void SetRecording(bool is_recording, bool is_overdub) {
-      this->is_overdub = is_overdub;
-      this->is_recording = is_recording || is_overdub;
-      //Initialize recording head position on start
-      // if (rec_env_pos_inc <= 0 && is_recording) {
-      if (is_recording) {
-        // rec_head = (loop_start + play_head) % buffer_length;
-        switch (rec_start_mode) {
-          case REC_START_MODE_LOOP:
-            rec_head = (loop_start) % buffer_length;
-            break;
-          case REC_START_MODE_BUFFER:
-            rec_head = 0.0f;
-            break;
-          case REC_START_MODE_PLAYHEAD:
-            rec_head = fmod(loop_start + play_head, float(buffer_length));
-            break;
-        }
-          
-        is_empty = false;
-      }
-      // When record switch changes state it effectively
-      // sets ramp to rising/falling, providing a
-      // fade in/out in the beginning and at the end of 
-      // the recorded region.
-      rec_env_pos_inc = is_recording ? 1 : -1;
-    }
-
-    void SetLoop(const float loop_start_time, const float loop_length_time) {
-      if (!isnan(loop_start_time)) {
-        loop_start_f = loop_start_time;
-        // Set the start of the next loop
-        pending_loop_start = static_cast<size_t>(loop_start_time * (buffer_length - 1));
+  private:
+    static const size_t kFadeLength = 200;
+    static const size_t kMinLoopLength = 2 * kFadeLength;
 
-        // If the current loop start is not set yet, set it too
-        if (!is_loop_set) loop_start = pending_loop_start;
-      }
+    float* buffer;
+    size_t buffer_length = 0;
 
-      if (!isnan(loop_length_time)) {
-        loop_length_f = loop_length_time;
-        // Set the length of the next loop
-        pendingloop_length = max(kMinLoopLength, static_cast<size_t>(loop_length_time * buffer_length));
+    Head playheads[9];
+    Head rec_head;
 
-        // CHECK if this is truly good
-        // loop_length = pendingloop_length;
-        // loop_length = pendingloop_length;
+    size_t loop_start = 0;
+    size_t loop_length = 48000;
 
-        //If the current loop length is not set yet, set it too
-        if (!is_loop_set) loop_length = pendingloop_length;
-      }
-      is_loop_set = true;
-    }
-  
-    void Record(float in) {
-      // Calculate iterator position on the record level ramp.
-      if (rec_env_pos_inc > 0 && rec_env_pos < kFadeLength
-       || rec_env_pos_inc < 0 && rec_env_pos > 0) {
-          rec_env_pos += rec_env_pos_inc;
-      }
-      // If we're in the middle of the ramp - record to the buffer.
-      if (rec_env_pos > 0) {
-        // Calculate fade in/out
-        float rec_attenuation = static_cast<float>(rec_env_pos) / static_cast<float>(kFadeLength);
-        if (this->is_overdub) {
-          buffer[int(rec_head)] += in * rec_attenuation;
-        } else {
-          buffer[int(rec_head)] = in * rec_attenuation + buffer[int(rec_head)] * (1.f - rec_attenuation);
-        }
+    bool stop_after_recording = false;
+    bool stay_within_loop = true;
 
-        // Set recording pitch mode
-        switch (rec_pitch_mode) {
-          case REC_PITCH_MODE_NORMAL: 
-            rec_head += 1.0f; 
-            break;
-          case REC_PITCH_MODE_UNPITCHED: 
-            rec_head += playback_increment; 
-            break;
-          case REC_PITCH_MODE_PITCHED:
-            if (playback_increment != 0.0) {
-              rec_head += 1.0f/playback_increment;
-            }
-            break;
-        }
+};
 
-        // Different recording modes
-        if (!stop_after_recording) {
-          if (!stay_within_loop) {
-            // record into whole buffer
-            rec_head = fmod(rec_head, float(buffer_length));
-          } else {
-            // Limit rec head to stay inside the loop
-            rec_head = fmod(rec_head, float(loop_start + loop_length));
-            rec_head = max(float(loop_start), rec_head);
-          }
-        } else {
-          if (!stay_within_loop) {
-            if (rec_head > buffer_length) { SetRecording(false, false); }
-          } else {
-            if (rec_head > loop_start + loop_length) { SetRecording(false, false); }
-          }
-        }
 
-        if (rec_head > buffer_length) {
-          rec_head = 0.0f;
-        } else if (rec_head < 0) {
-          rec_head = buffer_length;
+Looper::Looper() {}
+
+void Looper::Init(float *buf, size_t buf_size) {
+  buffer = buf;
+  buffer_length = buf_size;
+  memset(buffer, 0, sizeof(float) * buffer_length);
+}
+
+void Looper::SetRecord() {
+  recording_state = REC_STATE_RECORDING;
+  ResetRecHead();
+  rec_head.activate();
+}
+
+void Looper::SetOverdub() {
+  recording_state = REC_STATE_OVERDUBBING;
+  ResetRecHead();
+  rec_head.activate();
+}
+
+void Looper::SetErase() {
+  recording_state = REC_STATE_ERASING;
+  ResetRecHead();
+  rec_head.activate();
+}
+
+void Looper::SetStopWriting() {
+  recording_state = REC_STATE_NONE;
+  rec_head.deactivate();
+}
+
+bool Looper::isWriting() {
+  return recording_state == REC_STATE_RECORDING 
+    || recording_state == REC_STATE_OVERDUBBING 
+    || recording_state == REC_STATE_ERASING; 
+}
+
+void Looper::ResetRecHead() {
+  if (isWriting()) {
+    switch (rec_start_mode) {
+      case REC_START_MODE_LOOP:
+        rec_head.setPosition(loop_start % buffer_length);
+        break;
+      case REC_START_MODE_BUFFER:
+        rec_head.setPosition(0.0f);
+        break;
+      case REC_START_MODE_PLAYHEAD:
+        rec_head.setPosition(fmod(loop_start + playheads[0].read(), float(buffer_length)));
+        break;
+    }
+  }
+}
+
+void Looper::SetLoop(float loop_start_time, float loop_length_time) {
+  if (!isnan(loop_start_time)) {
+    loop_start_f = loop_start_time;
+    loop_start = static_cast<size_t>(loop_start_time * (buffer_length - 1));
+  }
+  if (!isnan(loop_length_time)) {
+    loop_length_f = loop_length_time;
+    loop_length = max(kMinLoopLength, static_cast<size_t>(loop_length_time * buffer_length));
+  }
+}
+
+void Looper::Record(float in) {
+  // Overwrite/Add/Erase the buffer depending on the mode
+  switch (recording_state) {
+    case REC_STATE_RECORDING:
+      buffer[int(rec_head.read())] = in;
+      break;
+    case REC_STATE_OVERDUBBING:
+      buffer[int(rec_head.read())] += in;
+      break;
+    case REC_STATE_ERASING:
+      buffer[int(rec_head.read())] = 0.0f;
+      break;
+  }
+
+  // Advance the recording head if needed
+  if (isWriting()) {
+    // Set Recording head increment depending on the mode
+    switch (rec_pitch_mode) {
+      case REC_PITCH_MODE_NORMAL: 
+        rec_head.setIncrement(1.0f); 
+        break;
+      case REC_PITCH_MODE_UNPITCHED: 
+        rec_head.setIncrement(playheads[0].increment); 
+        break;
+      case REC_PITCH_MODE_PITCHED:
+        if (playheads[0].increment != 0.0) {
+          rec_head.setIncrement(1.0f/playheads[0].increment);
         }
-        
-      }
+        break;
     }
-
-    float Process() {
-      // Early return if the buffer is empty
-      if (is_empty) {
-        return 0;
+    // Increment recording head
+    rec_head.update();
+
+    // Limit the position of the rec head depending on the active mode
+    if (!stop_after_recording) {
+      if (!stay_within_loop) {
+        // record into whole buffer
+        rec_head.setPosition(fmod(rec_head.read(), float(buffer_length)));
+      } else {
+        // Limit rec head to stay inside the loop
+        rec_head.setPosition(fmod(rec_head.read(), float(loop_start + loop_length)));
+        rec_head.setPosition(max(float(loop_start), rec_head.read()));
       }
-
-      // Variables for the Playback from the Buffer
-      float attenuation = 1;
-      float output = 0;
-
-      // Calculate fade in/out
-      if (play_head < kFadeLength) {
-        attenuation = static_cast<float>(play_head) / static_cast<float>(kFadeLength);
-      }
-      else if (play_head >= loop_length - kFadeLength) {
-        attenuation = static_cast<float>(loop_length - play_head) / static_cast<float>(kFadeLength);
+    } else {
+      // Stop at end (either end of buffer or end of loop)
+      if (!stay_within_loop) {
+        if (rec_head.read() > buffer_length) { SetStopWriting(); }
+      } else {
+        if (rec_head.read() > loop_start + loop_length) { SetStopWriting(); }
       }
-      
-      // Ensure we are actually inside the buffer
-      auto play_pos = int(loop_start + play_head) % buffer_length;
-
-      // Read from the buffer
-      output = buffer[play_pos] * attenuation;
-
-      // Advance playhead by the increment
-      play_head += playback_increment;
-
-      // Ensure the playhead stays within bounds of the loop
-      if (play_head >= loop_length) {
-        loop_start = pending_loop_start;
-        loop_length = pendingloop_length;
-        play_head = 0;
-      } else if (play_head <= 0) {
-        loop_start = pending_loop_start;
-        loop_length = pendingloop_length;
-        play_head = loop_length;
-      }
-      
-      // Return the attenuated signal
-      return output * attenuation;
     }
 
-    float GetPlayhead() {
-      return  float(play_head) / float(buffer_length);
-    }
-
-    float GetRecHead() {
-      return  float(rec_head) / float(buffer_length);
-    }
-
-    bool toggleRecMode() {
-      stay_within_loop = !stay_within_loop;
-      return stay_within_loop;
-    }
-
-    void setRecModeFull() {
-      stay_within_loop = false;
-      stop_after_recording = false;
-    }
-
-    void setRecModeLoop() {
-      stay_within_loop = true;
-      stop_after_recording = false;
-    }
-
-    void setRecModeFullShot() {
-      stay_within_loop = false;
-      stop_after_recording = true;
-    }
-
-    void setRecModeLoopShot() {
-      stay_within_loop = true;
-      stop_after_recording = true;
-    }
-
-
-    void setPlaybackSpeed(float increment) {
-      playback_increment = increment;
-    }
-
-    void addToPlayhead(float value) {
-      play_head += value;
-    }
-
-    float* getBuffer() {
-      return buffer;
-    }
-
-    size_t getBufferLength() {
-      return buffer_length;
+    // Ensure the Rec-Head is never without bounds, even when running backwards
+    if (rec_head.read() > buffer_length) {
+      rec_head.setPosition(0.0f);
+    } else if (rec_head.read() < 0) {
+      rec_head.setPosition(buffer_length);
     }
+  }
+}
+
+float Looper::Process() {
+  // Early return if buffer is empty or not playing to save performance
+  if (recording_state == REC_STATE_EMPTY 
+    || playback_state == PLAYBACK_STATE_STOPPED) {
+    return 0;
+  }
+
+  // Deactivate all playheads except first if playback state is Loop
+  switch (playback_state) {
+    case PLAYBACK_STATE_LOOP:
+      playheads[0].activate();
+      for (size_t i=1; i<9; i++) {
+        playheads[i].deactivate();
+      }
+      break;
+    case PLAYBACK_STATE_MULTILOOP:
+      for (size_t i=0; i<9; i++) {
+        playheads[i].activate();
+      }
+      break;
+    case PLAYBACK_STATE_STOPPED:
+      for (size_t i=0; i<9; i++) {
+        playheads[i].deactivate();
+      }
+      break;
+  }
 
-    bool isRecording() {
-      return is_recording;
-    }
+  double mix = 0.0;
 
-    bool isOverdubbing() {
-      return is_overdub;
-    }
+  for (size_t i=0; i<9; i++) {
+    // Skip inactive playheads
+    if (!playheads[i].isActive()) continue;
 
-    void setRecPitchMode(RecPitchMode mode) {
-      rec_pitch_mode = mode;
-    }
+    // Ensure we are actually inside the buffer
+    int play_pos = int(loop_start + playheads[i].read()) % buffer_length;
 
-    void setRecStartMode(RecStartMode mode) {
-      rec_start_mode = mode;
-    }
+    // Read from the buffer
+    mix += buffer[play_pos];
 
-    float loop_length_f = 1.0f;
-    float loop_start_f = 0.0f;
+    // Advance the playhead
+    playheads[i].update();
 
-  private:
-    static const size_t kFadeLength = 200;
-    static const size_t kMinLoopLength = 2 * kFadeLength;
+    // Ensure the playhead stays within bounds of the loop
+    if ((playheads[i].read()) >= loop_length) {
+        playheads[i].setPosition(0.0f);
+      } else if (playheads[i].read() <= 0.0f) {
+        playheads[i].setPosition(loop_length);
+      }
+  }
+  return saturate(mix);
+}
+
+float Looper::GetPlayhead() {
+  return float(playheads[0].read()) / float(buffer_length);
+}
+
+float* Looper::GetPlayheads() {
+  static float playhead_positions[9];
+  for (size_t i=0; i<9; i++) {
+    playhead_positions[i] = float(playheads[i].read()) / float(buffer_length);
+    Serial.print(playhead_positions[i]);
+    Serial.print(" ");
+  }
+  Serial.println("");
+  return playhead_positions;
+}
+
+float Looper::GetRecHead() {
+  return  float(rec_head.read()) / float(buffer_length);
+}
+
+bool Looper::toggleRecMode() {
+  stay_within_loop = !stay_within_loop;
+  return stay_within_loop;
+}
+
+void Looper::setRecModeFull() {
+  stay_within_loop = false;
+  stop_after_recording = false;
+}
+
+void Looper::setRecModeLoop() {
+  stay_within_loop = true;
+  stop_after_recording = false;
+}
+
+void Looper::setRecModeFullShot() {
+  stay_within_loop = false;
+  stop_after_recording = true;
+}
+
+void Looper::setRecModeLoopShot() {
+  stay_within_loop = true;
+  stop_after_recording = true;
+}
+
+void Looper::setPlaybackSpeed(float increment) {
+  switch (playback_state) {
+    case PLAYBACK_STATE_LOOP:
+      playheads[0].setIncrement(increment);
+      break;
+    case PLAYBACK_STATE_MULTILOOP:
+      playheads[0].setIncrement(increment);
+      for (size_t i=1; i<9; i++) {
+        playheads[i].setIncrement(increment + increment/(1+i));
+      }
+      break;
+  }
+}
+
+void Looper::addToPlayhead(float value) {
+  switch (playback_state) {
+    case PLAYBACK_STATE_LOOP:
+      playheads[0].incrementBy(value);
+      break;
+    case PLAYBACK_STATE_MULTILOOP:
+      playheads[0].incrementBy(value);
+      for (size_t i=1; i<9; i++) {
+        playheads[i].incrementBy(value + value/(1+i));
+      }
+      break;
+  }
+}
 
-    float* buffer;
+float* Looper::getBuffer() {
+  return buffer;
+}
 
-    size_t buffer_length       = 0;
-    size_t loop_length         = 48000;
-    size_t pendingloop_length = 0;
-    size_t loop_start          = 0;
-    size_t pending_loop_start  = 0;
+size_t Looper::getBufferLength() {
+  return buffer_length;
+}
 
-    float play_head = 0.0f;
-    float rec_head  = 0.0f;
+void Looper::setRecPitchMode(RecPitchMode mode) {
+  rec_pitch_mode = mode;
+}
 
-    float playback_increment = 1.0f;
+void Looper::setRecStartMode(RecStartMode mode) {
+  rec_start_mode = mode;
+}
 
-    size_t rec_env_pos      = 0;
-    int32_t rec_env_pos_inc = 0;
-    bool is_empty  = true;
-    bool is_loop_set = false;
-    bool stay_within_loop = false;
-    bool is_overdub = false;
-    bool is_recording = false;
-    bool stop_after_recording = false;
-};
 
-}; // namespace atoav
 
-#endif
\ No newline at end of file
+}; // namespace atoav
\ No newline at end of file
diff --git a/code/daisy-looper/ui.h b/code/daisy-looper/ui.h
index af65c5b0e1731f18aa72ec6cd25d9f46f1eb381b..288812cf764e8da30fe685930c6ba0b1a7da10a6 100644
--- a/code/daisy-looper/ui.h
+++ b/code/daisy-looper/ui.h
@@ -101,12 +101,12 @@ class Ui {
         GridButton("START\nLOOPST\nPLAYHD", &button_6, false, BUTTON_TYPE_MULTITOGGLE, 0, "START RECORDING AT\n\nSTART--->Start of the\n         Buffer\nLOOP---->Start of the\n         Loop\nPLAYH--->Position of\n         the Playhead"),
       }),
       ButtonGrid((int) UI_MODE_PLAY_MENU, {
-        GridButton("LOOP", &button_1, false),
+        GridButton(" ", &button_1, false),
         GridButton("PLAY\nMENU", &button_2, true),
         GridButton("ACTIVE\nSUM\nRING", &button_3, false, BUTTON_TYPE_MULTITOGGLE, 0),
-        GridButton("DRUNK", &button_4, false),
-        GridButton("GRAIN", &button_5, false),
-        GridButton("SHOT", &button_6, false),
+        GridButton("STOP\nLOOP\nMULTI\nMIDI", &button_4, false, BUTTON_TYPE_MULTITOGGLE, 1),
+        GridButton(" ", &button_5, false),
+        GridButton(" ", &button_6, false),
       }),
       ButtonGrid((int) UI_MODE_TRIGGER_MENU, {
         GridButton("MIDI\nTRIG.", &button_1, false),
@@ -415,25 +415,22 @@ class Ui {
       if (ui_mode == UI_MODE_PLAY_MENU && last_ui_mode != UI_MODE_PLAY_MENU) {
         int n = 1;
 
+        // Show the setting of the current buffer
+        button_grids[n].grid_buttons_[3].active = (int) activeLooper()->playback_state ;
+
         // Setup button Grid
         Button* home_button = setupButtonGrid(n);
 
-        // button_1.onPress([this, n](){ 
-
-        // });
         button_3.onPress([this, n](){ 
           button_grids[n].grid_buttons_[2].next();
           buffer_summing_mode = (BufferSummingMode) button_grids[n].grid_buttons_[2].active;
         });
-        // button_4.onPress([this, n](){ 
-        //
-        // });
-        // button_5.onPress([this, n](){ 
-        // 
-        // });
-        // button_6.onPress([this, n](){ 
-        // 
-        // });
+
+        button_4.onPress([this, n](){ 
+          button_grids[n].grid_buttons_[3].next();
+          // 0 is stop so we add one, check looper.h for definition of enum
+          activeLooper()->playback_state = (atoav::PlaybackState) (button_grids[n].grid_buttons_[3].active);
+        });
 
         // Store the last ui mode, for the check on top
         last_ui_mode = ui_mode;
@@ -573,14 +570,38 @@ class Ui {
       }
 
       // Draw Playhead
-      int x_playhead = int(activeLooper()->GetPlayhead() * display.width()) + x_start_loop;
-      display.drawLine(x_playhead, 6, x_playhead, 24, SH110X_WHITE);
+      switch (activeLooper()->playback_state) {
+        case atoav::PLAYBACK_STATE_LOOP:
+          {
+            int x_playhead = int(activeLooper()->GetPlayhead() * display.width()) + x_start_loop;
+            display.drawFastVLine(x_playhead, 6, 24, SH110X_WHITE);
+            break;
+          }
+        case atoav::PLAYBACK_STATE_MULTILOOP:
+          {
+            float* playheads = activeLooper()->GetPlayheads();
+            int x_playhead = 0;
+            for (size_t i=0; i<9; i++) {
+              x_playhead = int(playheads[i] * display.width()) + x_start_loop;
+              int h = 6 + i*3;
+              display.drawFastVLine(x_playhead, h, 3, SH110X_WHITE);
+            }
+            break;
+          }
+        case atoav::PLAYBACK_STATE_MIDI:
+          {
+            int x_playhead = int(activeLooper()->GetPlayhead() * display.width()) + x_start_loop;
+            display.drawFastVLine(x_playhead, 6, 24, SH110X_WHITE);
+            break;
+          }
+      }
+      
 
       // Draw Recording Indicator and Recording Head
       if (recording_state == REC_STATE_RECORDING) {
         // Draw Rec Head
         int x_rec_head = int(activeLooper()->GetRecHead() * display.width());
-        display.drawLine(x_rec_head, 10, x_rec_head, bottom, SH110X_WHITE);
+        display.drawFastVLine(x_rec_head, 10, bottom, SH110X_WHITE);
         display.fillCircle(x_rec_head, 10, 3, SH110X_WHITE);
         // Record sign
         display.fillRect(0, 0, 13, 13, SH110X_WHITE);
@@ -593,7 +614,7 @@ class Ui {
       if (recording_state == REC_STATE_OVERDUBBING) {
         // Draw Rec Head
         int x_rec_head = int(activeLooper()->GetRecHead() * display.width());
-        display.drawLine(x_rec_head, 10, x_rec_head, bottom, SH110X_WHITE);
+        display.drawFastVLine(x_rec_head, 10, bottom, SH110X_WHITE);
         display.fillCircle(x_rec_head, 10, 3, SH110X_WHITE);
 
         // Overdub sign (a "plus")
@@ -620,7 +641,7 @@ class Ui {
     // Activate recording and set the waveform cache to dirty
     void activateRecording() {
       if (recording_state != REC_STATE_RECORDING) {
-        activeLooper()->SetRecording(true, false);
+        activeLooper()->SetRecord();
         waveform_cache_dirty = true;
         recording_state = REC_STATE_RECORDING;
       }
@@ -646,7 +667,7 @@ class Ui {
       if (recording_state != REC_STATE_OVERDUBBING) {
         waveform_cache_dirty = true;
         recording_state = REC_STATE_OVERDUBBING;
-        activeLooper()->SetRecording(true, true);
+        activeLooper()->SetOverdub();
       }
     }
 
@@ -654,7 +675,7 @@ class Ui {
     void stopRecording() {
       if (recording_state != REC_STATE_NOT_RECORDING) {
         recording_state = REC_STATE_NOT_RECORDING;
-        activeLooper()->SetRecording(false, false);
+        activeLooper()->SetStopWriting();
       }
     }