diff --git a/components/bl00mbox/plugins/bl00mbox/bl00mbox_line_in.c b/components/bl00mbox/plugins/bl00mbox/bl00mbox_line_in.c
index a977a158cbe9fe168cf8c9295731c21fe5827bf2..2aa14d33da34adf82081f0598e5e27539f318c08 100644
--- a/components/bl00mbox/plugins/bl00mbox/bl00mbox_line_in.c
+++ b/components/bl00mbox/plugins/bl00mbox/bl00mbox_line_in.c
@@ -1,7 +1,7 @@
 #include "bl00mbox_line_in.h"
 
 radspa_descriptor_t bl00mbox_line_in_desc = {
-    .name = "line_in",
+    .name = "bl00mbox_line_in",
     .id = 4001,
     .description = "connects to the line input of bl00mbox",
     .create_plugin_instance = bl00mbox_line_in_create,
diff --git a/components/bl00mbox/plugins/sampler.c b/components/bl00mbox/plugins/sampler.c
index e4ff33b72db5348e3c81d4f64036590ab2ba1f97..1785815aa905fcb41016391f9c6a366ddaa61393 100644
--- a/components/bl00mbox/plugins/sampler.c
+++ b/components/bl00mbox/plugins/sampler.c
@@ -15,6 +15,12 @@ radspa_descriptor_t sampler_desc = {
 #define SAMPLER_REC_IN 2
 #define SAMPLER_REC_TRIGGER 3
 
+static int16_t define_behavior(uint32_t in){
+    int32_t ret = in & 0xFFFF;
+    if(ret > 32767) return ret - 65535;
+    return ret;
+}
+
 void sampler_run(radspa_t * sampler, uint16_t num_samples, uint32_t render_pass_id){
     radspa_signal_t * output_sig = radspa_signal_get_by_index(sampler, SAMPLER_OUTPUT);
     if(output_sig->buffer == NULL) return;
@@ -26,7 +32,14 @@ void sampler_run(radspa_t * sampler, uint16_t num_samples, uint32_t render_pass_
 
     static int32_t ret = 0;
     
-    uint32_t buffer_size = sampler->plugin_table_len;
+    buf[0] = define_behavior(data->read_head_position);
+    buf[1] = define_behavior(data->read_head_position>>16);
+    buf[2] = define_behavior(data->sample_start);
+    buf[3] = define_behavior(data->sample_start>>16);
+    buf[2] = define_behavior(data->sample_len);
+    buf[3] = define_behavior(data->sample_len>>16);
+    
+    uint32_t buffer_size = sampler->plugin_table_len - 6;
     
     for(uint16_t i = 0; i < num_samples; i++){
         int16_t rec_trigger = radspa_trigger_get(rec_trigger_sig->get_value(rec_trigger_sig, i, num_samples, render_pass_id), &(data->rec_trigger_prev));
@@ -52,7 +65,7 @@ void sampler_run(radspa_t * sampler, uint16_t num_samples, uint32_t render_pass_
 
         if(data->rec_active){
             int16_t rec_in = rec_in_sig->get_value(rec_in_sig, i, num_samples, render_pass_id);
-            buf[data->write_head_position] = rec_in;
+            buf[data->write_head_position + 6] = rec_in;
             data->write_head_position++;
             if(data->write_head_position >= buffer_size) data->write_head_position = 0;
             if(data->sample_len < buffer_size) data->sample_len++;
@@ -67,7 +80,7 @@ void sampler_run(radspa_t * sampler, uint16_t num_samples, uint32_t render_pass_
             if(data->read_head_position < data->sample_len){
                 uint32_t sample_offset_pos = data->read_head_position + data->sample_start;
                 if(sample_offset_pos >= data->sample_len) sample_offset_pos -= data->sample_len;
-                ret = radspa_mult_shift(buf[sample_offset_pos], data->volume);
+                ret = radspa_mult_shift(buf[sample_offset_pos + 6], data->volume);
                 data->read_head_position++;
             } else {
                 //ret = (ret * 255)>>8; // avoid dc clicks with bad samples
@@ -81,7 +94,7 @@ void sampler_run(radspa_t * sampler, uint16_t num_samples, uint32_t render_pass_
 radspa_t * sampler_create(uint32_t init_var){
     if(init_var == 0) return NULL; //doesn't make sense
     uint32_t buffer_size = init_var;
-    radspa_t * sampler = radspa_standard_plugin_create(&sampler_desc, SAMPLER_NUM_SIGNALS, sizeof(sampler_data_t), buffer_size);
+    radspa_t * sampler = radspa_standard_plugin_create(&sampler_desc, SAMPLER_NUM_SIGNALS, sizeof(sampler_data_t), buffer_size + 6*sizeof(int16_t);
     if(sampler == NULL) return NULL;
     sampler->render = sampler_run;
     radspa_signal_set(sampler, SAMPLER_OUTPUT, "output", RADSPA_SIGNAL_HINT_OUTPUT, 0);
diff --git a/python_payload/apps/tiny_sampler/__init__.py b/python_payload/apps/tiny_sampler/__init__.py
index c424b67b104c87d80e156b5df81004c724cb0475..2f5d88ee191da24535ef47816a382c15cc03cc45 100644
--- a/python_payload/apps/tiny_sampler/__init__.py
+++ b/python_payload/apps/tiny_sampler/__init__.py
@@ -16,10 +16,10 @@ class TinySampler(Application):
         self.blm = bl00mbox.Channel("tiny sampler")
 
         self.samplers = [None] * 5
-        self.line_in = self.blm.new(bl00mbox.plugins.line_in)
+        self.line_in = self.blm.new(bl00mbox.plugins.bl00mbox_line_in)
         self.line_in.signals.gain = 30000
         for i in range(5):
-            self.samplers[i] = self.blm.new(bl00mbox.patches.sampler, 5000)
+            self.samplers[i] = self.blm.new(bl00mbox.patches.sampler, 1000)
             self.samplers[i].signals.output = self.blm.mixer
             self.samplers[i].signals.rec_in = self.line_in.signals.mid
         self.is_recording = [False] * 5
@@ -82,6 +82,7 @@ class TinySampler(Application):
             ):
                 if self.is_recording[i]:
                     self.samplers[i].signals.rec_trigger.stop()
+                    self.samplers[i].normalize()
                     self.is_recording[i] = False
 
         self.ct_prev = ct
diff --git a/python_payload/bl00mbox/_patches.py b/python_payload/bl00mbox/_patches.py
index a4b5aa8634ae731330ef71b1dbce45630a42ab64..d3e32378e88fb44e62fa7d748f752b1a6bab1e38 100644
--- a/python_payload/bl00mbox/_patches.py
+++ b/python_payload/bl00mbox/_patches.py
@@ -100,7 +100,7 @@ class tinysynth_fm(tinysynth):
 
 class sampler(_Patch):
     """
-    requires a wave file. default path: /sys/samples/
+    requires a wave file (str) or max sample length in milliseconds (int). default path: /sys/samples/
     """
 
     def __init__(self, chan, init_var):
@@ -113,9 +113,9 @@ class sampler(_Patch):
             else:
                 f = wave.open("/flash/sys/samples/" + filename, "r")
 
-            self.len_frames = f.getnframes()
+            self._len_frames = f.getnframes()
             self.plugins.sampler = chan.new(
-                bl00mbox.plugins._sampler_ram, self.len_frames
+                bl00mbox.plugins._sampler_ram, self._len_frames
             )
 
             assert f.getsampwidth() == 2
@@ -125,22 +125,22 @@ class sampler(_Patch):
             if f.getnchannels() == 1:
                 # fast path for mono
                 table = self.plugins.sampler.table_bytearray
-                for i in range(0, self.len_frames * 2, 100):
-                    table[i : i + 100] = f.readframes(50)
+                for i in range(0, self._len_frames * 2, 100):
+                    table[i + 6 : i + 100 + 6] = f.readframes(50)
             else:
                 # somewhat fast path for stereo
                 table = self.plugins.sampler.table_int16_array
-                for i in range(self.len_frames):
+                for i in range(self._len_frames):
                     frame = f.readframes(1)
                     value = int.from_bytes(frame[0:2], "little")
-                    table[i] = value
+                    table[i + 6] = value
 
             f.close()
             self._filename = filename
         else:
-            self.len_frames = int(48 * init_var)
+            self._len_frames = int(48 * init_var)
             self.plugins.sampler = chan.new(
-                bl00mbox.plugins._sampler_ram, self.len_frames
+                bl00mbox.plugins._sampler_ram, self._len_frames
             )
             self._filename = ""
 
@@ -149,10 +149,51 @@ class sampler(_Patch):
         self.signals.rec_in = self.plugins.sampler.signals.rec_in
         self.signals.rec_trigger = self.plugins.sampler.signals.rec_trigger
 
+    def load(self, filename):
+        pass
+
+    def save(self, filename):
+        pass
+
+    def _extract_uint32_t(self, lsb, msb):
+        if lsb < 0:
+            lsb += 65535
+        if msb < 0:
+            msb += 65535
+        return lsb + (msb * (1<<16))
+
+    @property
+    def read_head_position(self):
+        return self._extract_uint32_t(self.plugins.sampler.table[0], self.plugins.sampler.table[1])
+
+    @property
+    def sample_start(self):
+        return self._extract_uint32_t(self.plugins.sampler.table[2], self.plugins.sampler.table[3])
+
+    @property
+    def sample_len(self):
+        return self._extract_uint32_t(self.plugins.sampler.table[4], self.plugins.sampler.table[5])
+
     @property
     def filename(self):
         return self._filename
 
+    def normalize(self):
+        maximum = 0
+        table = self.plugins.sampler.table_int16_array
+        for i in range(self.sample_len):
+            i = (i + self.sample_start) % self._len_frames
+            a = table[i+6]
+            if a < 0:
+                a = -a
+            if a > maximum:
+                maximum = a
+        if maximum != 0:
+            gain = 32767/maximum
+            for i in range(self.sample_len):
+                i = (i + self.sample_start) % self._len_frames
+                table[i+6] = gain * table[i+6]
+
 
 class sequencer(_Patch):
     def __init__(self, chan, num_tracks, num_steps):
@@ -188,6 +229,7 @@ class sequencer(_Patch):
             + str(self.signals.step_len.value)
         )
         ret += "\n  [tracks]"
+        """
         for x, seq in enumerate(self.seqs):
             ret += (
                 "\n    "
@@ -196,6 +238,7 @@ class sequencer(_Patch):
                 + "".join(["X  " if x > 0 else ".  " for x in seq.table[1:]])
                 + "]"
             )
+        """
         ret += "\n" + "\n".join(super().__repr__().split("\n")[1:])
         return ret