diff --git a/engine/drumkit.c b/engine/drumkit.c
index 97a4fdccee40d2a790d6a5c5bf10ab9d7d1618ab..0193446c1a3322c419229cd7deac716901f72b3f 100644
--- a/engine/drumkit.c
+++ b/engine/drumkit.c
@@ -13,6 +13,7 @@
 
 #include "drumkit.h"
 
+// Set default values on an instrument.
 static void instrument_set_defaults(struct instrument *ins) {
   ins->pan_l = ins->pan_r = 1;
   ins->gain = ins->volume = 1;
@@ -24,6 +25,7 @@ static void instrument_set_defaults(struct instrument *ins) {
   ins->note = 0;
 }
 
+// Return a sndfile format value in human-readable format.
 static char *sf_format_name(int format) {
   static char fmtbuf[32];
   const char *major = "weird", *subtype = NULL;
@@ -52,6 +54,7 @@ static char *sf_format_name(int format) {
   return fmtbuf;
 }
 
+// Dump instrument metadata to standard output.
 static void print_instrument(struct instrument *ins) {
   int i;
   printf("instrument %s: pan=%g/%g, gain=%g\n", ins->name, ins->pan_l,
@@ -64,8 +67,11 @@ static void print_instrument(struct instrument *ins) {
   }
 }
 
+// Return a string with the content of the result of an XPath
+// expression (which should evaluate the text() of a single node), or
+// NULL if the expression returned no nodes.
 static const char *xpath_value_as_string(xmlNodePtr node, const char *xpathExpr,
-                                   xmlXPathContextPtr xpathCtx) {
+                                         xmlXPathContextPtr xpathCtx) {
   xmlXPathObjectPtr res;
   const char *content;
   res = xmlXPathNodeEval(node, (const xmlChar *)xpathExpr, xpathCtx);
@@ -80,6 +86,9 @@ static const char *xpath_value_as_string(xmlNodePtr node, const char *xpathExpr,
   return content;
 }
 
+// Evaluate an XPath expression and store the result as a float. The
+// value pointed by out won't be modified if the XPath expression has
+// no result.
 static void xpath_get_float(float *out, xmlNodePtr node, const char *xpathExpr,
                             xmlXPathContextPtr xpathCtx) {
   const char *s;
@@ -91,6 +100,9 @@ static void xpath_get_float(float *out, xmlNodePtr node, const char *xpathExpr,
   *out = strtof(s, NULL);
 }
 
+// Evaluate an XPath expression and store the result as an
+// integer. The value pointed by out won't be modified if the XPath
+// expression has no result.
 static void xpath_get_int(int *out, xmlNodePtr node, const char *xpathExpr,
                           xmlXPathContextPtr xpathCtx) {
   const char *s;
@@ -102,12 +114,16 @@ static void xpath_get_int(int *out, xmlNodePtr node, const char *xpathExpr,
   *out = atoi(s);
 }
 
+// Evaluate an XPath expression and store the result as a string. The
+// value pointed by out won't be modified if the XPath expression has
+// no result. The string will always use newly allocated memory.
 static void xpath_get_string(char **out, xmlNodePtr node,
                              const char *xpathExpr,
                              xmlXPathContextPtr xpathCtx) {
   *out = strdup(xpath_value_as_string(node, xpathExpr, xpathCtx));
 }
 
+// Count the number of nodes returned by an XPath expression.
 static int xpath_count(xmlNodePtr node, const char *xpathExpr, xmlXPathContextPtr xpathCtx) {
   xmlXPathObjectPtr res;
   int n;
@@ -134,12 +150,15 @@ static char *path_dirname(const char *filename) {
   return buf;
 }
 
+// Join two path components. Return a newly allocated string.
 static char *path_join(const char *base, const char *filename) {
   char *buf = (char *)malloc(strlen(base) + strlen(filename) + 2);
   sprintf(buf, "%s/%s", base, filename);
   return buf;
 }
 
+// Load audio file data into a sample. Will convert the sample rate to
+// the desired target using libsamplerate.
 static int load_sample_data(struct sample *sample, SNDFILE *sndfile, int target_samplerate) {
   SF_INFO *info = &sample->info;
   float *tmp, *p, *wl, *wr;
@@ -192,24 +211,25 @@ static int load_sample_data(struct sample *sample, SNDFILE *sndfile, int target_
   return 1;
 }
 
+// Load an audio file into a sample. Will convert the sample rate to
+// the desired target using libsamplerate.
 static int load_sample(struct sample *sample, const char *path, int target_samplerate) {
   SF_INFO *info = &sample->info;
   SNDFILE *sndfile;
-  int r = 1;
+  int r;
 
   sndfile = sf_open(path, SFM_READ, info);
   if (!sndfile) {
-    printf("failed to open sample %s: %s\n", path, sf_strerror(NULL));
+    fprintf(stderr, "failed to open sample %s: %s\n", path, sf_strerror(NULL));
     return 0;
   }
 
-  // Read all the sample data.
-  if (!load_sample_data(sample, sndfile, target_samplerate)) {
-    printf("failed to load sample data from %s\n", path);
-    r = 0;
-  }
-
+  // Read the sample data and convert it to the desired format/rate.
+  r = load_sample_data(sample, sndfile, target_samplerate);
   sf_close(sndfile);
+  if (!r) {
+    fprintf(stderr, "failed to load sample data from %s\n", path);
+  }
   return r;
 }
 
@@ -222,6 +242,7 @@ static void free_sample(struct sample *sample) {
   }
 }
 
+// Parse an instrument layer from an XML document.
 static int parse_layer(struct layer *layer, xmlNodePtr node,
                        xmlXPathContextPtr xpathCtx, const char *basedir,
                        int target_samplerate) {
@@ -246,6 +267,7 @@ static void free_layer(struct layer *layer) {
   free_sample(&layer->sample);
 }
 
+// Parse an instrument from an XML document.
 static int parse_instrument(struct instrument *ins, xmlNodePtr node,
                             xmlXPathContextPtr xpathCtx, const char *basedir,
                             int target_samplerate) {
@@ -309,17 +331,19 @@ static void free_instrument(struct instrument *ins) {
   free(ins->name);
 }
 
+// Find the instrument layer corresponding to a specific velocity.
 struct layer *instrument_find_layer_by_velocity(struct instrument *ins, float velocity) {
   int i;
 
   for (i = 0; i < ins->num_layers; i++) {
-    if (ins->layers[i].max > velocity) {
+    if (velocity >= ins->layers[i].min && velocity <= ins->layers[i].max) {
       return &ins->layers[i];
     }
   }
   return &ins->layers[ins->num_layers - 1];
 }
 
+// Parse a list of instruments from an XML document.
 static int parse_instruments(struct instrument **instruments,
                              xmlNodeSetPtr nodes, xmlXPathContextPtr xpathCtx,
                              const char *basedir, int target_samplerate) {
@@ -345,7 +369,11 @@ static void free_instruments(struct instrument *instruments, int n) {
   }
 }
 
-void fix_midi_notes(struct drumkit *kit) {
+// Some drumkits lack an explicit MIDI note assignment: these are
+// recognizable because they set all instruments to the same MIDI
+// note. We can detect this situation and fix it with a default note
+// assignment.
+static void fix_midi_notes(struct drumkit *kit) {
   int note_count[127] = {0};
   int note_cardinality = 0;
   int i;
@@ -377,6 +405,7 @@ struct drumkit *drumkit_new(const char *filename, int target_samplerate) {
   return kit;
 }
 
+// Assign the Hydrogen drumkit namespace to all XML nodes in a document.
 static void fix_bad_xml(xmlNodePtr cur, xmlNsPtr ns) {
   for (; cur; cur = cur->next) {
     if (cur->type == XML_ELEMENT_NODE) {