diff --git a/docs/badge/bl00mbox.rst b/docs/badge/bl00mbox.rst
index 20a820d5d6f53393f7ded102f03ad70cd29e2bb6..10366dad5ba8ce508d22c710e6b16da8ada69368 100644
--- a/docs/badge/bl00mbox.rst
+++ b/docs/badge/bl00mbox.rst
@@ -278,6 +278,28 @@ Some other misc channel operations for live coding mostly:
       plugins: 0
       [channel mixer] (0 connections)
 
+Radspa signal types
+------------------------
+
+Radspa is a C plugin format that all bl00mbox plugins are written in. Its main feature is that all signals
+are expressed in the same manner so that every input->output connection is valid. This means that for real
+world value interpretation some decoding is sometimes necessary. While the REPL informs you of these
+quanta and helper functions such as .start() or .dB() help with first contact, for interfacing with these
+signals with another signal some understanding is helpful. The data is represented as an int16_t stream.
+
+[pitch] provides a logarithmic frequency input. A value of 18367 represents A440, going up by 1 represents
+0.5 cent or 1/2400 octaves or a factor of 2^(1/2400). Special methods: .tone can be set to (float) semitones
+distance from A440 or a note name such as "F#4", .freq can be set to a value in Hz
+
+[gain] provides a linear volume input. A value of 4096 represents unity gain. Special methods: .mult is linear
+and represents unity gain as 1, .dB is 20*log_10(x) and represents unity gain as 0.
+
+[trigger] provides an input for note start/stop events. A start event with a given velocity (midi term, think
+loudness, 1..32767) from a stopped state is encoded by a permanent signal change to the velocity value. A
+restart from this "running" state is encoded as permanently flipping the signal sign, i.e to [-1..-32676] and
+back to [1..32767] on the next restart. A change from nonzero to zero encodes a signal stop. Note: This API is
+still subject to change.
+
 Example 1: Auto bassline
 ------------------------
 
diff --git a/python_payload/bl00mbox/_user.py b/python_payload/bl00mbox/_user.py
index a882af9acb989425a6cf33d8d516501421645834..b9c9bf9aaa441b6addae046ea222d1f59b348f19 100644
--- a/python_payload/bl00mbox/_user.py
+++ b/python_payload/bl00mbox/_user.py
@@ -87,6 +87,12 @@ class Signal:
         self._hints = ""
 
     def __repr__(self):
+        ret = self._no_desc()
+        if len(self._description):
+            ret += "\n  " + "\n  ".join(self._description.split("\n"))
+        return ret
+
+    def _no_desc(self):
         self._plugin._check_existence()
 
         ret = self.name
@@ -126,6 +132,9 @@ class Signal:
         if isinstance(self, SignalPitchMixin):
             ret += " / " + str(self.tone) + " semitones / " + str(self.freq) + "Hz"
 
+        if isinstance(self, SignalVolumeMixin):
+            ret += " / " + str(self.dB) + "dB / x" + str(self.mult)
+
         return ret
 
     @property
@@ -271,6 +280,24 @@ class SignalPitchMixin:
         self.value = (32767 - 2400 * 6) + 200 * tone
 
 
+class SignalVolumeMixin:
+    @property
+    def dB(self):
+        return 20 * math.log((self.value / 4096), 10)
+
+    @dB.setter
+    def dB(self, val):
+        self.value = int(4096 * (10 ** (val / 20)))
+
+    @property
+    def mult(self):
+        return self.value / 4096
+
+    @mult.setter
+    def mult(self, val):
+        self.value = int(4096 * val)
+
+
 class SignalInputTrigger(SignalInput, SignalTriggerMixin):
     pass
 
@@ -279,6 +306,10 @@ class SignalInputPitch(SignalInput, SignalPitchMixin):
     pass
 
 
+class SignalInputVolume(SignalInput, SignalVolumeMixin):
+    pass
+
+
 class SignalList:
     def __init__(self, plugin):
         self._list = []
@@ -298,6 +329,9 @@ class SignalList:
                 elif hints & 32:
                     signal = SignalInputPitch(plugin, signal_num)
                     signal._hints = "input/pitch"
+                elif hints & 8:
+                    signal = SignalInputVolume(plugin, signal_num)
+                    signal._hints = "input/volume"
                 else:
                     signal = SignalInput(plugin, signal_num)
                     signal._hints = "input"
@@ -335,7 +369,7 @@ class Plugin:
         self._check_existence()
         ret = "[plugin " + str(self.bud_num) + "] " + self.name
         for sig in self.signals._list:
-            ret += "\n  " + "\n  ".join(repr(sig).split("\n"))
+            ret += "\n  " + "\n  ".join(sig._no_desc().split("\n"))
         return ret
 
     def __del__(self):
@@ -502,6 +536,10 @@ class Channel:
         else:
             print("no active channels")
 
+    def print_plugins(self):
+        for plugin in self.plugins:
+            print(repr(plugin))
+
     def new(self, thing, init_var=None):
         self.free = False
         if type(thing) == type: