changeset 160:5bcf04234f80 heavy-updated

- added -std=c99 to Makefile for user-supplied C files (required for heavy files) - changed heavy core render.cpp file to use latest API and removed all redundant functions (e.g. foleyDesigner/touchkey stuff) - use build_pd.sh to compile and run pd files (-h for usage instructions)
author chnrx <chris.heinrichs@gmail.com>
date Thu, 05 Nov 2015 18:58:26 +0000
parents 1e7db6610600
children 07735c9d95c8
files Makefile projects/heavy/hello-world/ControlBinop.c projects/heavy/hello-world/ControlBinop.h projects/heavy/hello-world/ControlRandom.c projects/heavy/hello-world/ControlRandom.h projects/heavy/hello-world/ControlSystem.c projects/heavy/hello-world/ControlSystem.h projects/heavy/hello-world/ControlUnop.c projects/heavy/hello-world/ControlUnop.h projects/heavy/hello-world/ControlVar.c projects/heavy/hello-world/ControlVar.h projects/heavy/hello-world/Heavy.c projects/heavy/hello-world/HeavyMath.h projects/heavy/hello-world/Heavy_bbb.h projects/heavy/hello-world/HvBase.c projects/heavy/hello-world/HvBase.h projects/heavy/hello-world/HvContext_bbb.c projects/heavy/hello-world/HvContext_bbb.h projects/heavy/hello-world/HvMessage.c projects/heavy/hello-world/HvMessage.h projects/heavy/hello-world/HvTable.c projects/heavy/hello-world/HvTable.h projects/heavy/hello-world/MessagePool.c projects/heavy/hello-world/MessagePool.h projects/heavy/hello-world/MessageQueue.c projects/heavy/hello-world/MessageQueue.h projects/heavy/hello-world/SignalDel1.c projects/heavy/hello-world/SignalDel1.h projects/heavy/hello-world/SignalPhasor.c projects/heavy/hello-world/SignalPhasor.h projects/heavy/hello-world/SignalRPole.c projects/heavy/hello-world/SignalRPole.h projects/heavy/hello-world/SignalSamphold.c projects/heavy/hello-world/SignalSamphold.h projects/heavy/hello-world/SignalVar.c projects/heavy/hello-world/SignalVar.h projects/heavy/hello-world/Utils.h projects/heavy/hello-world/Utils_mac.c projects/heavy/hello-world/Utils_mac.h projects/heavy/hello-world/Utils_unix.c projects/heavy/hello-world/Utils_unix.h projects/heavy/hello-world/Utils_windows.c projects/heavy/hello-world/Utils_windows.h projects/heavy/hello-world/render.cpp projects/heavy/pd/hello-world/_main.pd projects/heavy/pd/samphold/_main.pd projects/heavy/samphold/ControlBinop.c projects/heavy/samphold/ControlBinop.h projects/heavy/samphold/ControlRandom.c projects/heavy/samphold/ControlRandom.h projects/heavy/samphold/ControlSystem.c projects/heavy/samphold/ControlSystem.h projects/heavy/samphold/ControlUnop.c projects/heavy/samphold/ControlUnop.h projects/heavy/samphold/ControlVar.c projects/heavy/samphold/ControlVar.h projects/heavy/samphold/Heavy.c projects/heavy/samphold/HeavyMath.h projects/heavy/samphold/Heavy_bbb.h projects/heavy/samphold/HvBase.c projects/heavy/samphold/HvBase.h projects/heavy/samphold/HvContext_bbb.c projects/heavy/samphold/HvContext_bbb.h projects/heavy/samphold/HvMessage.c projects/heavy/samphold/HvMessage.h projects/heavy/samphold/HvTable.c projects/heavy/samphold/HvTable.h projects/heavy/samphold/MessagePool.c projects/heavy/samphold/MessagePool.h projects/heavy/samphold/MessageQueue.c projects/heavy/samphold/MessageQueue.h projects/heavy/samphold/SignalDel1.c projects/heavy/samphold/SignalDel1.h projects/heavy/samphold/SignalPhasor.c projects/heavy/samphold/SignalPhasor.h projects/heavy/samphold/SignalRPole.c projects/heavy/samphold/SignalRPole.h projects/heavy/samphold/SignalSamphold.c projects/heavy/samphold/SignalSamphold.h projects/heavy/samphold/SignalVar.c projects/heavy/samphold/SignalVar.h projects/heavy/samphold/Utils.h projects/heavy/samphold/Utils_mac.c projects/heavy/samphold/Utils_mac.h projects/heavy/samphold/Utils_unix.c projects/heavy/samphold/Utils_unix.h projects/heavy/samphold/Utils_windows.c projects/heavy/samphold/Utils_windows.h projects/heavy/samphold/render.cpp scripts/build_pd.sh scripts/hvresources/render.cpp scripts/hvresources/uploader.py
diffstat 92 files changed, 10898 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun Oct 18 01:13:40 2015 +0100
+++ b/Makefile	Thu Nov 05 18:58:26 2015 +0000
@@ -87,7 +87,7 @@
 build/source/%.o: ./source/%.c
 	@echo 'Building file: $<'
 	@echo 'Invoking: GCC C Compiler'
-	gcc $(SYNTAX_FLAG) -I./include $(INCLUDES) -O2 -Wall -c -fmessage-length=0 -U_FORTIFY_SOURCE -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
+	gcc $(SYNTAX_FLAG) -I./include $(INCLUDES) -O2 -Wall -c -fmessage-length=0 -U_FORTIFY_SOURCE -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" -std=c99
 	@echo 'Finished building: $<'
 	@echo ' '
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlBinop.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlBinop.h"
+
+hv_size_t cBinop_init(ControlBinop *o, float k) {
+  o->k = k;
+  return 0;
+}
+
+static float cBinop_perform_op(BinopType op, float f, const float k) {
+  switch (op) {
+    case HV_BINOP_ADD: return f + k;
+    case HV_BINOP_SUBTRACT: return f - k;
+    case HV_BINOP_MULTIPLY: return f * k;
+    case HV_BINOP_DIVIDE: return (k != 0.0f) ? f / k : 0.0f;
+    case HV_BINOP_INT_DIV: return (float) ((int) f / (int) k);
+    case HV_BINOP_MOD_BIPOLAR: return (float) ((int) f % (int) k);
+    case HV_BINOP_MOD_UNIPOLAR: {
+      f = (k == 0.0f) ? 0.0f : (float) ((int) f % (int) k);
+      return (f < 0.0f) ? f + fabsf(k) : f;
+    }
+    case HV_BINOP_BIT_LEFTSHIFT: return (float) (((int) f) << ((int) k));
+    case HV_BINOP_BIT_RIGHTSHIFT: return (float) (((int) f) >> ((int) k));
+    case HV_BINOP_BIT_AND: return (float) ((int) f & (int) k);
+    case HV_BINOP_BIT_XOR: return (float) ((int) f ^ (int) k);
+    case HV_BINOP_BIT_OR: return (float) ((int) f | (int) k);
+    case HV_BINOP_EQ: return (f == k) ? 1.0f : 0.0f;
+    case HV_BINOP_NEQ: return (f != k) ? 1.0f : 0.0f;
+    case HV_BINOP_LOGICAL_AND: return ((f == 0.0f) || (k == 0.0f)) ? 0.0f : 1.0f;
+    case HV_BINOP_LOGICAL_OR: return ((f == 0.0f) && (k == 0.0f)) ? 0.0f : 1.0f;
+    case HV_BINOP_LESS_THAN: return (f < k) ? 1.0f : 0.0f;
+    case HV_BINOP_LESS_THAN_EQL: return (f <= k) ? 1.0f : 0.0f;
+    case HV_BINOP_GREATER_THAN: return (f > k) ? 1.0f : 0.0f;
+    case HV_BINOP_GREATER_THAN_EQL: return (f >= k) ? 1.0f : 0.0f;
+    case HV_BINOP_MAX: return hv_max_f(f, k);
+    case HV_BINOP_MIN: return hv_min_f(f, k);
+    case HV_BINOP_POW: return (f > 0.0f) ? powf(f, k) : 0.0f;
+    case HV_BINOP_ATAN2: return ((f == 0.0f) && (k == 0.0f)) ? 0.0f : atan2f(f, k);
+    default: return 0.0f;
+  }
+}
+
+void cBinop_onMessage(HvBase *_c, ControlBinop *o, BinopType op, int letIn,
+    const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+  switch (letIn) {
+    case 0: {
+      if (msg_isFloat(m, 0)) {
+        // Note(joe): supporting Pd's ability to perform operations of packs
+        // of floats is likely to not be supported in the future.
+        if (msg_isFloat(m, 1)) o->k = msg_getFloat(m, 1);
+        HvMessage *n = HV_MESSAGE_ON_STACK(1);
+        float f = cBinop_perform_op(op, msg_getFloat(m, 0), o->k);
+        msg_initWithFloat(n, msg_getTimestamp(m), f);
+        sendMessage(_c, 0, n);
+      }
+      break;
+    }
+    case 1: {
+      if (msg_isFloat(m, 0)) {
+        o->k = msg_getFloat(m, 0);
+      }
+      break;
+    }
+    default: break;
+  }
+}
+
+void cBinop_k_onMessage(HvBase *_c, void *o, BinopType op, const float k,
+    int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+  if (msg_isFloat(m, 0)) {
+    // NOTE(mhroth): Heavy does not support sending bangs to binop objects to return the previous output
+    float f = (msg_isFloat(m, 1)) ? msg_getFloat(m, 1) : k;
+    HvMessage *n = HV_MESSAGE_ON_STACK(1);
+    f = cBinop_perform_op(op, msg_getFloat(m, 0), f);
+    msg_initWithFloat(n, msg_getTimestamp(m), f);
+    sendMessage(_c, 0, n);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlBinop.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_BINOP_H_
+#define _HEAVY_CONTROL_BINOP_H_
+
+#include "HvBase.h"
+
+typedef enum BinopType {
+  HV_BINOP_ADD,
+  HV_BINOP_SUBTRACT,
+  HV_BINOP_MULTIPLY,
+  HV_BINOP_DIVIDE,
+  HV_BINOP_INT_DIV,
+  HV_BINOP_MOD_BIPOLAR,
+  HV_BINOP_MOD_UNIPOLAR,
+  HV_BINOP_BIT_LEFTSHIFT,
+  HV_BINOP_BIT_RIGHTSHIFT,
+  HV_BINOP_BIT_AND,
+  HV_BINOP_BIT_XOR,
+  HV_BINOP_BIT_OR,
+  HV_BINOP_EQ,
+  HV_BINOP_NEQ,
+  HV_BINOP_LOGICAL_AND,
+  HV_BINOP_LOGICAL_OR,
+  HV_BINOP_LESS_THAN,
+  HV_BINOP_LESS_THAN_EQL,
+  HV_BINOP_GREATER_THAN,
+  HV_BINOP_GREATER_THAN_EQL,
+  HV_BINOP_MAX,
+  HV_BINOP_MIN,
+  HV_BINOP_POW,
+  HV_BINOP_ATAN2
+} BinopType;
+
+typedef struct ControlBinop {
+  float k;
+} ControlBinop;
+
+hv_size_t cBinop_init(ControlBinop *o, float k);
+
+void cBinop_onMessage(HvBase *_c, ControlBinop *o, BinopType op, int letIn,
+    const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+void cBinop_k_onMessage(HvBase *_c, void *o, BinopType op, const float k,
+    int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+#endif // _HEAVY_CONTROL_BINOP_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlRandom.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlRandom.h"
+#include "HvBase.h"
+
+// http://www.firstpr.com.au/dsp/rand31
+// http://en.wikipedia.org/wiki/Lehmer_random_number_generator
+
+hv_size_t cRandom_init(ControlRandom *o, int seed) {
+  o->state = (seed != 0) ? seed : 1;
+  return 0;
+}
+
+void cRandom_onMessage(HvBase *_c, ControlRandom *o, int inletIndex, const HvMessage *m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *)) {
+  switch (inletIndex) {
+    case 0: {
+      HvMessage *n = HV_MESSAGE_ON_STACK(1);
+      o->state = (int) ((((unsigned long long) o->state) * 279470273UL) % 4294967291UL);
+      float f = ((float) (o->state >> 9)) * 0.00000011920929f;
+      msg_initWithFloat(n, msg_getTimestamp(m), f);
+      sendMessage(_c, 0, n);
+      break;
+    }
+    case 1: {
+      if (msg_isFloat(m,0)) {
+        o->state = (int) msg_getFloat(m,0);
+      }
+      break;
+    }
+    default: break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlRandom.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_RANDOM_H_
+#define _HEAVY_CONTROL_RANDOM_H_
+
+#include "HvBase.h"
+
+typedef struct ControlRandom {
+  unsigned int state;
+} ControlRandom;
+
+hv_size_t cRandom_init(ControlRandom *o, int seed);
+
+void cRandom_onMessage(HvBase *_c, ControlRandom *o, int letIndex, const HvMessage *m,
+  void (*sendMessage)(HvBase *, int, const HvMessage *));
+
+#endif // _HEAVY_CONTROL_RANDOM_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlSystem.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlSystem.h"
+#include "HvTable.h"
+
+void cSystem_onMessage(HvBase *_c, void *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+
+  HvMessage *n = HV_MESSAGE_ON_STACK(1);
+  if (msg_compareSymbol(m, 0, "samplerate")) {
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) ctx_getSampleRate(_c));
+  } else if (msg_compareSymbol(m, 0, "numInputChannels")) {
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) ctx_getNumInputChannels(_c));
+  } else if (msg_compareSymbol(m, 0, "numOutputChannels")) {
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) ctx_getNumOutputChannels(_c));
+  } else if (msg_compareSymbol(m, 0, "currentTime")) {
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) msg_getTimestamp(m));
+  } else if (msg_compareSymbol(m, 0, "table")) {
+    // NOTE(mhroth): no need to check message format for symbols as table lookup will fail otherwise
+    HvTable *o = ctx_getTableForHash(_c, msg_getHash(m,1));
+    if (o != NULL) {
+      if (msg_compareSymbol(m, 2, "length")) {
+        msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getLength(o));
+      } else if (msg_compareSymbol(m, 2, "size")) {
+        msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getSize(o));
+      } else if (msg_compareSymbol(m, 2, "head")) {
+        msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getHead(o));
+      } else return;
+    } else return;
+  } else return;
+  sendMessage(_c, 0, n);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlSystem.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_SYSTEM_H_
+#define _HEAVY_CONTROL_SYSTEM_H_
+
+#include "HvBase.h"
+
+void cSystem_onMessage(HvBase *_c, void *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+#endif // _HEAVY_CONTROL_SYSTEM_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlUnop.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlUnop.h"
+#include "HvBase.h"
+
+void cUnop_onMessage(HvBase *_c, UnopType op, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const )) {
+  if (msg_isFloat(m, 0)) {
+    float f = msg_getFloat(m, 0);
+    switch (op) {
+      case HV_UNOP_SIN: f = hv_sin_f(f); break;
+      case HV_UNOP_SINH: f = hv_sinh_f(f); break;
+      case HV_UNOP_COS: f = hv_cos_f(f); break;
+      case HV_UNOP_COSH: f = hv_cosh_f(f); break;
+      case HV_UNOP_TAN: f = hv_tan_f(f); break;
+      case HV_UNOP_TANH: f = hv_tanh_f(f); break;
+      case HV_UNOP_ASIN: f = hv_asin_f(f); break;
+      case HV_UNOP_ASINH: f = hv_asinh_f(f); break;
+      case HV_UNOP_ACOS: f = hv_acos_f(f); break;
+      case HV_UNOP_ACOSH: f = hv_acosh_f(f); break;
+      case HV_UNOP_ATAN: f = hv_atan_f(f); break;
+      case HV_UNOP_ATANH: f = hv_atanh_f(f); break;
+      case HV_UNOP_EXP: f = hv_exp_f(f); break;
+      case HV_UNOP_ABS: f = hv_abs_f(f); break;
+      case HV_UNOP_SQRT: f = (f > 0.0f) ? hv_sqrt_f(f) : 0.0f; break;
+      case HV_UNOP_LOG: f = (f > 0.0f) ? hv_log_f(f) : 0.0f; break;
+      case HV_UNOP_LOG2: f = (f > 0.0f) ? hv_log2_f(f) : 0.0f; break;
+      case HV_UNOP_LOG10: f = (f > 0.0f) ? hv_log10_f(f) : 0.0f; break;
+      case HV_UNOP_CEIL: f = hv_ceil_f(f); break;
+      case HV_UNOP_FLOOR: f = hv_floor_f(f); break;
+      case HV_UNOP_ROUND: f = hv_round_f(f); break;
+      default: return;
+    }
+    HvMessage *n = HV_MESSAGE_ON_STACK(1);
+    msg_initWithFloat(n, m->timestamp, f);
+    sendMessage(_c, 0, n);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlUnop.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_UNOP_H_
+#define _HEAVY_CONTROL_UNOP_H_
+
+struct HvBase;
+struct HvMessage;
+
+typedef enum UnopType {
+  HV_UNOP_ASIN,
+  HV_UNOP_ASINH,
+  HV_UNOP_ACOS,
+  HV_UNOP_ACOSH,
+  HV_UNOP_ATAN,
+  HV_UNOP_ATANH,
+  HV_UNOP_SIN,
+  HV_UNOP_SINH,
+  HV_UNOP_COS,
+  HV_UNOP_COSH,
+  HV_UNOP_TAN,
+  HV_UNOP_TANH,
+  HV_UNOP_EXP,
+  HV_UNOP_ABS,
+  HV_UNOP_SQRT,
+  HV_UNOP_LOG,
+  HV_UNOP_LOG2,
+  HV_UNOP_LOG10,
+  HV_UNOP_CEIL,
+  HV_UNOP_FLOOR,
+  HV_UNOP_ROUND
+} UnopType;
+
+void cUnop_onMessage(struct HvBase *_c, UnopType op, const struct HvMessage *const m,
+    void (*sendMessage)(struct HvBase *, int, const struct HvMessage *const));
+
+#endif // _HEAVY_CONTROL_UNOP_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlVar.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlVar.h"
+
+hv_size_t cVar_init_f(ControlVar *o, float k) {
+  o->e.type = FLOAT;
+  o->e.data.f = k;
+  return 0;
+}
+
+hv_size_t cVar_init_s(ControlVar *o, const char *s) {
+  o->e.type = HASH;
+  o->e.data.h = msg_symbolToHash(s);
+  return 0;
+}
+
+void cVar_free(ControlVar *o) {
+  // nothing to do
+}
+
+void cVar_onMessage(HvBase *_c, ControlVar *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+  switch (letIn) {
+    case 0: {
+      switch (msg_getType(m,0)) {
+        case BANG: {
+          HvMessage *n = HV_MESSAGE_ON_STACK(1);
+          if (o->e.type == FLOAT) msg_initWithFloat(n, msg_getTimestamp(m), o->e.data.f);
+          else if (o->e.type == HASH) msg_initWithHash(n, msg_getTimestamp(m), o->e.data.h);
+          else return;
+          sendMessage(_c, 0, n);
+          break;
+        }
+        case FLOAT: {
+          o->e.type = FLOAT;
+          o->e.data.f = msg_getFloat(m,0);
+          sendMessage(_c, 0, m);
+          break;
+        }
+        case SYMBOL:
+        case HASH: {
+          o->e.type = HASH;
+          o->e.data.h = msg_getHash(m,0);
+          sendMessage(_c, 0, m);
+          break;
+        }
+        default: return;
+      }
+      break;
+    }
+    case 1: {
+      switch (msg_getType(m,0)) {
+        case FLOAT: {
+          o->e.type = FLOAT;
+          o->e.data.f = msg_getFloat(m,0);
+          break;
+        }
+        case SYMBOL:
+        case HASH: {
+          o->e.type = HASH;
+          o->e.data.h = msg_getHash(m,0);
+          break;
+        }
+        default: break;
+      }
+    }
+    default: return;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/ControlVar.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_VAR_H_
+#define _HEAVY_CONTROL_VAR_H_
+
+#include "HvBase.h"
+
+typedef struct ControlVar {
+  Element e; // type is only every FLOAT or HASH
+} ControlVar;
+
+hv_size_t cVar_init_f(ControlVar *o, float k);
+
+hv_size_t cVar_init_s(ControlVar *o, const char *s);
+
+void cVar_free(ControlVar *o);
+
+void cVar_onMessage(HvBase *_c, ControlVar *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+#endif // _HEAVY_CONTROL_VAR_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Heavy.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,196 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "HvBase.h"
+#include "HvTable.h"
+
+#if !HV_WIN
+#pragma mark - Heavy Table
+#endif
+
+int hv_table_resize(HvTable *o, hv_uint32_t newLength) {
+  return hTable_resize(o, newLength);
+}
+
+float *hv_table_getBuffer(HvTable *o) {
+  return hTable_getBuffer(o);
+}
+
+hv_size_t hv_table_getLength(HvTable *o) {
+  return hTable_getLength(o);
+}
+
+
+
+#if !HV_WIN
+#pragma mark - Heavy Message
+#endif
+
+hv_size_t hv_msg_getByteSize (hv_uint32_t numElements) {
+  return msg_getByteSize(numElements);
+}
+
+void hv_msg_init(HvMessage *m, int numElements, hv_uint32_t timestamp) {
+  msg_init(m, numElements, timestamp);
+}
+
+hv_size_t hv_msg_getNumElements(const HvMessage *const m) {
+  return msg_getNumElements(m);
+}
+
+double hv_msg_getTimestamp(const HvMessage *const m) {
+  return msg_getTimestamp(m);
+}
+
+void hv_msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp) {
+  msg_setTimestamp(m, timestamp);
+}
+
+bool hv_msg_isBang(const HvMessage *const m, int i) {
+  return msg_isBang(m,i);
+}
+
+void hv_msg_setBang(HvMessage *m, int i) {
+  msg_setBang(m,i);
+}
+
+bool hv_msg_isFloat(const HvMessage *const m, int i) {
+  return msg_isFloat(m, i);
+}
+
+float hv_msg_getFloat(const HvMessage *const m, int i) {
+  return msg_getFloat(m,i);
+}
+
+void hv_msg_setFloat(HvMessage *m, int i, float f) {
+  msg_setFloat(m,i,f);
+}
+
+bool hv_msg_isSymbol(const HvMessage *const m, int i) {
+  return msg_isSymbol(m,i);
+}
+
+char *hv_msg_getSymbol(const HvMessage *const m, int i) {
+  return msg_getSymbol(m,i);
+}
+
+void hv_msg_setSymbol(HvMessage *m, int i, char *s) {
+  msg_setSymbol(m,i,s);
+}
+
+bool hv_msg_isHash(const HvMessage *const m, int i) {
+  return msg_isHash(m, i);
+}
+
+unsigned int hv_msg_getHash(const HvMessage *const m, int i) {
+  return msg_getHash(m, i);
+}
+
+bool hv_msg_hasFormat(const HvMessage *const m, const char *fmt) {
+  return msg_hasFormat(m, fmt);
+}
+
+char *hv_msg_toString(const HvMessage *const m) {
+  return msg_toString(m);
+}
+
+HvMessage *hv_msg_copy(HvMessage *m) {
+  return msg_copy(m);
+}
+
+void hv_msg_free(HvMessage *m) {
+  msg_free(m);
+}
+
+
+
+#if !HV_WIN
+#pragma mark - Heavy Common
+#endif
+
+double hv_getSampleRate(HvBase *c) {
+  return ctx_getSampleRate(c);
+}
+
+int hv_getNumInputChannels(HvBase *c) {
+  return ctx_getNumInputChannels(c);
+}
+
+int hv_getNumOutputChannels(HvBase *c) {
+  return ctx_getNumOutputChannels(c);
+}
+
+const char *hv_getName(HvBase *c) {
+  return ctx_getName(c);
+}
+
+void hv_setPrintHook(HvBase *c, void (*f)(double, const char *, const char *, void *)) {
+  ctx_setPrintHook(c, f);
+}
+
+void hv_setSendHook(HvBase *c, void (*f)(double, const char *, const HvMessage *const, void *)) {
+  ctx_setSendHook(c, f);
+}
+
+void hv_vscheduleMessageForReceiver(HvBase *c, const char *receiverName, const double delayMs, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  const int numElem = (int) hv_strlen(format);
+  HvMessage *m = HV_MESSAGE_ON_STACK(numElem);
+  msg_init(m, numElem, c->blockStartTimestamp + (hv_uint32_t) (hv_max_d(0.0, delayMs)*ctx_getSampleRate(c)/1000.0));
+  for (int i = 0; i < numElem; i++) {
+    switch (format[i]) {
+      case 'b': msg_setBang(m,i); break;
+      case 'f': msg_setFloat(m, i, (float) va_arg(ap, double)); break;
+      case 's': msg_setSymbol(m, i, (char *) va_arg(ap, char *)); break;
+      default: break;
+    }
+  }
+  ctx_scheduleMessageForReceiver(c, receiverName, m);
+
+  va_end(ap);
+}
+
+void hv_scheduleMessageForReceiver(HvBase *c, const char *receiverName, double delayMs, HvMessage *m) {
+  hv_assert(delayMs >= 0.0);
+  msg_setTimestamp(m, c->blockStartTimestamp + (hv_uint32_t) (delayMs*ctx_getSampleRate(c)/1000.0));
+  ctx_scheduleMessageForReceiver(c, receiverName, m);
+}
+
+HvTable *hv_getTableForName(HvBase *c, const char *tableName) {
+  return ctx_getTableForName(c, tableName);
+}
+
+void hv_cancelMessage(HvBase *c, HvMessage *m) {
+  ctx_cancelMessage(c, m, NULL);
+}
+
+double hv_getCurrentTime(HvBase *c) {
+  return ((double) c->blockStartTimestamp)/c->sampleRate;
+}
+
+void *hv_getUserData(HvBase *c) {
+  return ctx_getUserData(c);
+}
+
+void hv_setUserData(HvBase *c, void *userData) {
+  ctx_setUserData(c, userData);
+}
+
+void hv_setBasePath(HvBase *c, const char *basePath) {
+  ctx_setBasePath(c, basePath);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HeavyMath.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,645 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_MATH_H_
+#define _HEAVY_MATH_H_
+
+#include "Utils.h"
+
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/
+// https://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/ARM-NEON-Intrinsics.html
+// http://codesuppository.blogspot.co.uk/2015/02/sse2neonh-porting-guide-and-header-file.html
+
+static inline void __hv_zero_f(hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_setzero_ps();
+#elif HV_SIMD_SSE
+  *bOut = _mm_setzero_ps();
+#elif HV_SIMD_NEON
+  *bOut = vdupq_n_f32(0.0f);
+#else // HV_SIMD_NONE
+  *bOut = 0.0f;
+#endif
+}
+
+static inline void __hv_load_f(float *bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_load_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_load_ps(bIn);
+#elif HV_SIMD_NEON
+  *bOut = vld1q_f32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = *bIn;
+#endif
+}
+
+static inline void __hv_store_f(float *bOut, hv_bInf_t bIn) {
+#if HV_SIMD_AVX
+  _mm256_store_ps(bOut, bIn);
+#elif HV_SIMD_SSE
+  _mm_store_ps(bOut, bIn);
+#elif HV_SIMD_NEON
+  vst1q_f32(bOut, bIn);
+#else // HV_SIMD_NONE
+  *bOut = bIn;
+#endif
+}
+
+static inline void __hv_log_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_log_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_log_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_log_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = (bIn > 0.0f) ? hv_log_f(bIn) : 0.0f;
+#endif
+}
+
+static inline void __hv_log10_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_log10_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_log10_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_log10_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = (bIn > 0.0f) ? hv_log10_f(bIn) : 0.0f;
+#endif
+}
+
+static inline void __hv_log2_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_log2_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_log2_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_log2_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = (bIn > 0.0f) ? hv_log2_f(bIn) : 0.0f;
+#endif
+}
+
+// NOTE(mhroth): this is a pretty ghetto implementation
+static inline void __hv_cos_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_set_ps(
+      hv_cos_f(bIn[7]), hv_cos_f(bIn[6]), hv_cos_f(bIn[5]), hv_cos_f(bIn[4]),
+      hv_cos_f(bIn[3]), hv_cos_f(bIn[2]), hv_cos_f(bIn[1]), hv_cos_f(bIn[0]));
+#elif HV_SIMD_SSE
+  *bOut = _mm_set_ps(hv_cos_f(bIn[3]), hv_cos_f(bIn[2]), hv_cos_f(bIn[1]), hv_cos_f(bIn[0]));
+#elif HV_SIMD_NEON
+  *bOut = (float32x4_t) {hv_cos_f(bIn[0]), hv_cos_f(bIn[1]), hv_cos_f(bIn[2]), hv_cos_f(bIn[3])};
+#else // HV_SIMD_NONE
+  *bOut = hv_cos_f(bIn);
+#endif
+}
+
+static inline void __hv_acos_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_acos_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_acos_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_acos_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_acos_f(bIn);
+#endif
+}
+
+static inline void __hv_cosh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_cosh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_cosh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_cosh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_cosh_f(bIn);
+#endif
+}
+
+static inline void __hv_acosh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_acosh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_acosh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_acosh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_acosh_f(bIn);
+#endif
+}
+
+static inline void __hv_sin_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_sin_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_sin_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_sin_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_sin_f(bIn);
+#endif
+}
+
+static inline void __hv_asin_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_asin_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_asin_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_asin_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_asin_f(bIn);
+#endif
+}
+
+static inline void __hv_sinh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_sinh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_sinh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_sinh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_sinh_f(bIn);
+#endif
+}
+
+static inline void __hv_asinh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_asinh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_asinh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_asinh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_asinh_f(bIn);
+#endif
+}
+
+static inline void __hv_tan_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_tan_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_tan_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_tan_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_tan_f(bIn);
+#endif
+}
+
+static inline void __hv_atan_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_atan_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_atan_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_atan_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_atan_f(bIn);
+#endif
+}
+
+static inline void __hv_atan2_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_atan2_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_atan2_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_atan2_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_atan2_f(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_tanh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_tanh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_tanh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_tanh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_tanh_f(bIn);
+#endif
+}
+
+static inline void __hv_atanh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_atanh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_atanh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_atanh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_atanh_f(bIn);
+#endif
+}
+
+// NOTE(mhroth): use of sqrt is absolute and total MURDER. Make do with recipocal sqrt if possible!!
+static inline void __hv_sqrt_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_sqrt_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_sqrt_ps(bIn);
+#elif HV_SIMD_NEON
+#warning __hv_sqrt_f() numerical results may be inexact
+  *bOut = vrecpeq_f32(vrsqrteq_f32(bIn));
+#else // HV_SIMD_NONE
+  *bOut = hv_sqrt_f(bIn);
+#endif
+}
+
+static inline void __hv_rsqrt_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_rsqrt_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_rsqrt_ps(bIn);
+#elif HV_SIMD_NEON
+#warning __hv_rsqrt_f() numerical results may be inexact
+  *bOut = vrsqrteq_f32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = 1.0f/hv_sqrt_f(bIn);
+#endif
+}
+
+static inline void __hv_abs_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_andnot_ps(_mm_set1_ps(-0.0f), bIn); // == 1 << 31
+#elif HV_SIMD_NEON
+  *bOut = vabsq_f32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = hv_abs_f(bIn);
+#endif
+}
+
+static inline void __hv_exp_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_exp_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_exp_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_exp_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_exp_f(bIn);
+#endif
+}
+
+static inline void __hv_ceil_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_ceil_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_ceil_ps(bIn);
+#elif HV_SIMD_NEON
+#if __ARM_ARCH >= 8
+  *bOut = vrndpq_f32(bIn);
+#else
+#warning A slow NEON implementation of __hv_ceil_f() is being used because the necessary intrinsic cannot be found. It is only available in ARMv8.
+  *bOut = (float32x4_t) {hv_ceil_f(bIn[0]), hv_ceil_f(bIn[1]), hv_ceil_f(bIn[2]), hv_ceil_f(bIn[3])};
+#endif // vrndpq_f32
+#else // HV_SIMD_NONE
+  *bOut = hv_ceil_f(bIn);
+#endif
+}
+
+static inline void __hv_floor_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_floor_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_floor_ps(bIn);
+#elif HV_SIMD_NEON
+#if __ARM_ARCH >= 8
+  *bOut = vrndmq_f32(bIn);
+#else
+#warning A slow NEON implementation of __hv_floor_f() is being used because the necessary intrinsic cannot be found. It is only available in ARMv8.
+  *bOut = (float32x4_t) {hv_floor_f(bIn[0]), hv_floor_f(bIn[1]), hv_floor_f(bIn[2]), hv_floor_f(bIn[3])};
+#endif // vrndmq_f32
+#else // HV_SIMD_NONE
+  *bOut = hv_floor_f(bIn);
+#endif
+}
+
+// __add~f
+static inline void __hv_add_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_add_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_add_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vaddq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 + bIn1;
+#endif
+}
+
+// __add~i
+static inline void __hv_add_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  __m128i x = _mm_add_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1));
+  __m128i y = _mm_add_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1));
+  *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_add_epi32(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vaddq_s32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 + bIn1;
+#endif
+}
+
+// __sub~f
+static inline void __hv_sub_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_sub_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_sub_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vsubq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 - bIn1;
+#endif
+}
+
+// __mul~f
+static inline void __hv_mul_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_mul_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_mul_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vmulq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 * bIn1;
+#endif
+}
+
+// __*~i
+static inline void __hv_mul_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  __m128i x = _mm_mullo_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1));
+  __m128i y = _mm_mullo_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1));
+  *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_mullo_epi32(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vmulq_s32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 * bIn1;
+#endif
+}
+
+// __cast~if
+static inline void __hv_cast_if(hv_bIni_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cvtepi32_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cvtepi32_ps(bIn);
+#elif HV_SIMD_NEON
+  *bOut = vcvtq_f32_s32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = (float) bIn;
+#endif
+}
+
+// __cast~fi
+static inline void __hv_cast_fi(hv_bInf_t bIn, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cvtps_epi32(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cvtps_epi32(bIn);
+#elif HV_SIMD_NEON
+  *bOut = vcvtq_s32_f32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = (int) bIn;
+#endif
+}
+
+static inline void __hv_div_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_div_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_div_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+#warning __hv_div_f() numerical results may be inexact
+  *bOut = vmulq_f32(bIn0, vrecpeq_f32(bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn1 != 0.0f) ? (bIn0 / bIn1) : 0.0f;
+#endif
+}
+
+static inline void __hv_min_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_min_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_min_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vminq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = hv_min_f(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_min_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  __m128i x = _mm_min_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1));
+  __m128i y = _mm_min_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1));
+  *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_min_epi32(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vminq_s32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = hv_min_i(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_max_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_max_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_max_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vmaxq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = hv_max_f(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_max_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  __m128i x = _mm_max_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1));
+  __m128i y = _mm_max_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1));
+  *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_max_epi32(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vmaxq_s32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = hv_max_i(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_pow_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_set_ps(
+      hv_pow_f(bIn0[7], bIn1[7]),
+      hv_pow_f(bIn0[6], bIn1[6]),
+      hv_pow_f(bIn0[5], bIn1[5]),
+      hv_pow_f(bIn0[4], bIn1[4]),
+      hv_pow_f(bIn0[3], bIn1[3]),
+      hv_pow_f(bIn0[2], bIn1[2]),
+      hv_pow_f(bIn0[1], bIn1[1]),
+      hv_pow_f(bIn0[0], bIn1[0]));
+#elif HV_SIMD_SSE
+  *bOut = _mm_set_ps(
+      hv_pow_f(bIn0[3], bIn1[3]),
+      hv_pow_f(bIn0[2], bIn1[2]),
+      hv_pow_f(bIn0[1], bIn1[1]),
+      hv_pow_f(bIn0[0], bIn1[0]));
+#elif HV_SIMD_NEON
+  *bOut = (float32x4_t) {
+      hv_pow_f(bIn0[0], bIn1[0]),
+      hv_pow_f(bIn0[1], bIn1[1]),
+      hv_pow_f(bIn0[2], bIn1[2]),
+      hv_pow_f(bIn0[3], bIn1[3])};
+#else // HV_SIMD_NONE
+  *bOut = hv_pow_f(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_gt_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_GT_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmpgt_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vcgtq_f32(bIn0, bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 > bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_gte_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_GE_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmpge_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vcgeq_f32(bIn0, bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 >= bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_lt_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_LT_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmplt_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vcltq_f32(bIn0, bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 < bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_lte_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_LE_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmple_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vcleq_f32(bIn0, bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 <= bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_neq_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_NEQ_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmpneq_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vmvnq_u32(vceqq_f32(bIn0, bIn1)));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 != bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_xor_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_xor_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_xor_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_xor_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = (float) (((int) bIn0) ^ ((int) bIn1));
+#endif
+}
+
+static inline void __hv_and_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_and_ps(bIn1, bIn0);
+#elif HV_SIMD_SSE
+  *bOut = _mm_and_ps(bIn1, bIn0);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(bIn1), vreinterpretq_u32_f32(bIn0)));
+#else // HV_SIMD_NONE
+  if (bIn0 == 0.0f || bIn1 == 0.0f) *bOut = 0.0f;
+  else if (bIn0 == 1.0f) *bOut = bIn1;
+  else if (bIn1 == 1.0f) *bOut = bIn0;
+  else hv_assert(0); // TODO(mhroth): floating point & is pretty much a bad idea, only used for if~
+#endif
+}
+
+// bOut = (bIn0 * bIn1) + bIn2
+static inline void __hv_fma_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bInf_t bIn2, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#if HV_SIMD_FMA
+  *bOut = _mm256_fmadd_ps(bIn0, bIn1, bIn2);
+#else
+  *bOut = _mm256_add_ps(_mm256_mul_ps(bIn0, bIn1), bIn2);
+#endif // HV_SIMD_FMA
+#elif HV_SIMD_SSE
+#if HV_SIMD_FMA
+  *bOut = _mm_fmadd_ps(bIn0, bIn1, bIn2);
+#else
+  *bOut = _mm_add_ps(_mm_mul_ps(bIn0, bIn1), bIn2);
+#endif // HV_SIMD_FMA
+#elif HV_SIMD_NEON
+#if __ARM_ARCH >= 8
+  *bOut = vfmaq_f32(bIn2, bIn0, bIn1);
+#else
+  // NOTE(mhroth): it turns out, fma SUUUUCKS on lesser ARM architectures
+  // But in fact ideally fma would be disabled in ir2c for ARM architectures.
+  // LLVM does a much better job handling fma than we do.
+  *bOut = vaddq_f32(vmulq_f32(bIn0, bIn1), bIn2);
+#endif
+#else // HV_SIMD_NONE
+  *bOut = hv_fma_f(bIn0, bIn1, bIn2);
+#endif
+}
+
+#endif // _HEAVY_MATH_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Heavy_bbb.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,241 @@
+
+/**
+ * Copyright (c) 2014,2015 Enzien Audio, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, and/or
+ * sublicense copies of the Software, strictly on a non-commercial basis,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * DO NOT MODIFY. THIS CODE IS MACHINE GENERATED BY THE SECTION6 HEAVY COMPILER.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "Utils.h"
+
+#if !HV_MSVC
+#pragma mark - Heavy Table
+#endif
+
+#ifndef _HEAVY_TABLE_H_
+#define _HEAVY_TABLE_H_
+
+typedef struct HvTable HvTable;
+
+/**
+ * Resizes the table to the given length. Length must be positive.
+ * Existing contents are copied to the new table. Remaining space is cleared.
+ * The change in byte-size of the table is returned. A value of zero indicates error.
+ */
+HV_EXPORT int hv_table_resize(HvTable *o, hv_uint32_t newLength);
+
+/** Returns a pointer to the raw buffer backing this table. DO NOT free it. */
+HV_EXPORT float *hv_table_getBuffer(HvTable *o);
+
+/** Returns the length of this table in samples. */
+HV_EXPORT int hv_table_getLength(HvTable *o);
+
+#endif // _HEAVY_TABLE_H_
+
+
+
+#if !HV_MSVC
+#pragma mark - Heavy Message
+#endif
+
+#ifndef _HEAVY_MESSAGE_H_
+#define _HEAVY_MESSAGE_H_
+
+HV_EXPORT typedef struct HvMessage HvMessage;
+
+/** Returns the byte size of a HvMessage with a number of elements on the heap. */
+HV_EXPORT hv_size_t hv_msg_getByteSize(int numElements);
+
+/** Create a HvMessage on the stack with a number of elements. This message MUST NOT be freed. */
+#define hv_msg_onStack(_n) ((HvMessage *) hv_alloca(hv_msg_getByteSize(_n)))
+
+/** Initialise a message with the number of elements and a timestamp (in milliseconds). */
+HV_EXPORT void hv_msg_init(HvMessage *m, int numElements, double timestamp);
+
+/** Returns the number of elements in this message. */
+HV_EXPORT int hv_msg_getNumElements(const HvMessage *const m);
+
+/** Returns the time at which this message exists (in milliseconds). */
+HV_EXPORT hv_uint32_t hv_msg_getTimestamp(const HvMessage *const m);
+
+/** Set the time at which this message should be executed (in milliseconds). */
+HV_EXPORT void hv_msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp);
+
+/** Returns true of the indexed element is a bang. False otherwise. Index is not bounds checked. */
+HV_EXPORT bool hv_msg_isBang(const HvMessage *const m, int i);
+
+/** Sets the indexed element to a bang. Index is not bounds checked. */
+HV_EXPORT void hv_msg_setBang(HvMessage *m, int i);
+
+/** Returns true of the indexed element is a float. False otherwise. Index is not bounds checked. */
+HV_EXPORT bool hv_msg_isFloat(const HvMessage *const m, int i);
+
+/** Returns the indexed element as a float value. Index is not bounds checked. */
+HV_EXPORT float hv_msg_getFloat(const HvMessage *const m, int i);
+
+/** Sets the indexed element to float value. Index is not bounds checked. */
+HV_EXPORT void hv_msg_setFloat(HvMessage *m, int i, float f);
+
+/** Returns true of the indexed element is a symbol. False otherwise. Index is not bounds checked. */
+HV_EXPORT bool hv_msg_isSymbol(const HvMessage *const m, int i);
+
+/** Returns the indexed element as a symbol value. Index is not bounds checked. */
+HV_EXPORT char *hv_msg_getSymbol(const HvMessage *const m, int i);
+
+/** Returns true of the indexed element is a hash. False otherwise. Index is not bounds checked. */
+HV_EXPORT bool hv_msg_isHash(const HvMessage *const m, int i);
+
+/** Returns the indexed element as a hash value. Index is not bounds checked. */
+HV_EXPORT unsigned int hv_msg_getHash(const HvMessage *const m, int i);
+
+/** Sets the indexed element to symbol value. Index is not bounds checked. */
+HV_EXPORT void hv_msg_setSymbol(HvMessage *m, int i, const char *s);
+
+/**
+ * Returns true if the message has the given format, in number of elements and type. False otherwise.
+ * Valid element types are:
+ * 'b': bang
+ * 'f': float
+ * 's': symbol
+ *
+ * For example, a message with three floats would have a format of "fff". A single bang is "b".
+ * A message with two symbols is "ss". These types can be mixed and matched in any way.
+ */
+HV_EXPORT bool hv_msg_hasFormat(const HvMessage *const m, const char *fmt);
+
+/**
+ * Returns a basic string representation of the message.
+ * The character array MUST be deallocated by the caller.
+ */
+HV_EXPORT char *hv_msg_toString(const HvMessage *const m);
+
+/** Copy a message onto the stack. The message persists. */
+HV_EXPORT HvMessage *hv_msg_copy(const HvMessage *const m);
+
+/** Free a copied message. */
+HV_EXPORT void hv_msg_free(HvMessage *m);
+
+#endif // _HEAVY_MESSAGE_H_
+
+
+
+#if !HV_MSVC
+#pragma mark - Heavy Patch
+#endif
+
+#ifndef _HEAVY_BBB_H_
+#define _HEAVY_BBB_H_
+
+typedef struct Hv_bbb Hv_bbb;
+
+/**
+ * Creates a new patch instance.
+ * Sample rate should be positive and in Hertz.
+ */
+HV_EXPORT Hv_bbb *hv_bbb_new(double sampleRate);
+
+/**
+ * Creates a new patch instance.
+ * Sample rate should be positive and in Hertz.
+ * Pool size is in kilobytes, and determines the maximum amount of memory
+ *   allocated to messages at any time. By default this is 10.
+ */
+HV_EXPORT Hv_bbb *hv_bbb_new_with_pool(double sampleRate, int poolKb);
+
+/** Frees a patch instance. */
+HV_EXPORT void hv_bbb_free(Hv_bbb *c);
+
+/** Processes one block of samples for a patch instance. The buffer format is an array of float channel arrays. */
+HV_EXPORT int hv_bbb_process(Hv_bbb *c, float **const inputBuffers, float **const outputBuffers, int n4);
+
+/** Processes one block of samples for a patch instance. The buffer format is an uninterleaved float array of channels. */
+HV_EXPORT int hv_bbb_process_inline(Hv_bbb *c, float *const inputBuffers, float *const outputBuffers, int n4);
+
+/** Processes one block of samples for a patch instance. The buffer format is an interleaved short array of channels. */
+HV_EXPORT int hv_bbb_process_inline_short(Hv_bbb *c, short *const inputBuffers, short *const outputBuffers, int n4);
+#endif // _HEAVY_BBB_H_
+
+
+
+#if !HV_MSVC
+#pragma mark - Heavy Common
+#endif
+
+#ifndef _HEAVY_COMMON_H_
+#define _HEAVY_COMMON_H_
+
+typedef void Heavy;
+
+/** Returns the sample rate with which this patch has been configured. */
+HV_EXPORT double hv_getSampleRate(Heavy *c);
+
+/** Returns the number of input channels with which this patch has been configured. */
+HV_EXPORT int hv_getNumInputChannels(Heavy *c);
+
+/** Returns the number of output channels with which this patch has been configured. */
+HV_EXPORT int hv_getNumOutputChannels(Heavy *c);
+
+/** Set the print hook. The function is called whenever a message is sent to a print object. */
+HV_EXPORT void hv_setPrintHook(Heavy *c,
+    void (*f)(double timestamp, const char *printName, const char *message, void *userData));
+
+/**
+ * Set the send hook. The function is called whenever a message is sent to any send object.
+ * Messages returned by this function should NEVER be freed. If the message must persist, call
+ * hv_msg_copy() first.
+ */
+HV_EXPORT void hv_setSendHook(Heavy *c, void (*f)(double timestamp, const char *receiverName, const HvMessage *const m, void *userData));
+
+HV_EXPORT void hv_vscheduleMessageForReceiver(
+    Heavy *c, const char *receiverName, double delayMs, const char *format, ...);
+
+HV_EXPORT void hv_scheduleMessageForReceiver(Heavy *c, const char *receiverName, double delayMs, HvMessage *m);
+
+/** Cancels a previously scheduled message. */
+HV_EXPORT void hv_cancelMessage(Heavy *c, HvMessage *m);
+
+/** Returns a table object given its name. NULL if no table with that name exists. */
+HV_EXPORT HvTable *hv_getTableForName(Heavy *c, const char *tableName);
+
+/** Returns the current patch time in milliseconds. */
+HV_EXPORT double hv_getCurrentTime(Heavy *c);
+
+/** Sets a user-definable value. This value is never manipulated by Heavy. */
+HV_EXPORT void hv_setUserData(Heavy *c, void *userData);
+
+/** Returns the user-defined data. */
+HV_EXPORT void *hv_getUserData(Heavy *c);
+
+/** Define the base path of the patch. Used as the root path to locate assets. */
+HV_EXPORT void hv_setBasePath(Heavy *c, const char *basePath);
+
+/** Returns the read-only user-assigned name of this patch. */
+HV_EXPORT const char *hv_getName(Heavy *c);
+
+#endif // _HEAVY_COMMON_H_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HvBase.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "HvBase.h"
+
+void ctx_setBasePath(HvBase *const _c, const char *basePath) {
+  hv_free(_c->basePath);
+  if (basePath != NULL) {
+    hv_size_t len = (hv_size_t) hv_strlen(basePath);
+    _c->basePath = (char *) hv_malloc((len+1)*sizeof(char));
+    hv_strncpy(_c->basePath, basePath, len);
+  }
+}
+
+void ctx_cancelMessage(HvBase *_c, HvMessage *m, void (*sendMessage)(HvBase *, int, const HvMessage *)) {
+  mq_removeMessage(&_c->mq, m, sendMessage);
+}
+
+void ctx_scheduleMessageForReceiverV(HvBase *const _c, const char *name,
+    const hv_uint32_t timestamp, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  const int numElem = (int) hv_strlen(format);
+  HvMessage *m = HV_MESSAGE_ON_STACK(numElem);
+  msg_init(m, numElem, timestamp);
+  for (int i = 0; i < numElem; i++) {
+    switch (format[i]) {
+      case 'b': msg_setBang(m,i); break;
+      case 'f': msg_setFloat(m, i, (float) va_arg(ap, double)); break;
+      case 's': msg_setSymbol(m, i, (char *) va_arg(ap, char *)); break;
+      default: break;
+    }
+  }
+  _c->f_scheduleMessageForReceiver(_c, name, m);
+
+  va_end(ap);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HvBase.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_BASE_H_
+#define _HEAVY_BASE_H_
+
+#include "MessageQueue.h"
+#include "Utils.h"
+
+#define Base(_x) ((HvBase *) _x)
+
+typedef struct HvBase {
+  int numInputChannels;
+  int numOutputChannels;
+  double sampleRate;
+  hv_uint32_t blockStartTimestamp;
+  unsigned int numBytes; // the total number of bytes allocated for this patch
+  void (*f_scheduleMessageForReceiver)(struct HvBase *const, const char *, HvMessage *);
+  struct HvTable *(*f_getTableForHash)(struct HvBase *const, hv_uint32_t);
+  MessageQueue mq;
+  void (*printHook)(double, const char *, const char *, void *);
+  void (*sendHook)(double, const char *, const HvMessage *const, void *);
+  char *basePath;
+  void *userData;
+  const char *name;
+} HvBase;
+
+/**
+ * Schedule a message in the message queue according to its timestamp.
+ * The copy of the message added to the queue is returned.
+ */
+static inline HvMessage *ctx_scheduleMessage(HvBase *_c, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *), int outletIndex) {
+  return mq_addMessageByTimestamp(&_c->mq, (HvMessage *) m, outletIndex, sendMessage);
+}
+
+static inline void ctx_scheduleMessageForReceiver(HvBase *const _c,
+    const char *name, HvMessage *m) {
+  _c->f_scheduleMessageForReceiver(_c, name, m);
+}
+
+void ctx_scheduleMessageForReceiverV(HvBase *const _c, const char *name,
+    const hv_uint32_t timestamp, const char *format, ...);
+
+void ctx_cancelMessage(HvBase *_c, HvMessage *m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *));
+
+static inline int ctx_millisecondsToSamples(HvBase *_c, float timeInMs) {
+  return (int) (timeInMs * _c->sampleRate / 1000.0);
+}
+
+static inline double ctx_samplesToMilliseconds(HvBase *_c, int samples) {
+  return 1000.0 * samples / _c->sampleRate;
+}
+
+static inline double ctx_getSampleRate(HvBase *_c) {
+  return _c->sampleRate;
+}
+
+static inline int ctx_getNumInputChannels(HvBase *_c) {
+  return _c->numInputChannels;
+}
+
+static inline int ctx_getNumOutputChannels(HvBase *_c) {
+  return _c->numOutputChannels;
+}
+
+static inline const char *ctx_getName(HvBase *_c) {
+  return _c->name;
+}
+
+/** Returns the first sample of the block. */
+static inline hv_uint32_t ctx_getBlockStartTimestamp(HvBase *_c) {
+  return _c->blockStartTimestamp;
+}
+
+static inline void ctx_setPrintHook(HvBase *const _c, void (*f)(double,
+    const char *, const char *, void *)) {
+  _c->printHook = f;
+}
+
+static inline void ctx_setSendHook(HvBase *const _c, void (*f)(double, const char *, const HvMessage *const, void *)) {
+  _c->sendHook = f;
+}
+
+static inline void *ctx_getUserData(HvBase *const _c) {
+  return _c->userData;
+}
+
+static inline void ctx_setUserData(HvBase *const _c, void *userData) {
+  _c->userData = userData;
+}
+
+void ctx_setBasePath(HvBase *const _c, const char *basePath);
+
+static inline const char *ctx_getBasePath(HvBase *const _c) {
+  return _c->basePath;
+}
+
+static inline struct HvTable *ctx_getTableForHash(HvBase *const _c, hv_uint32_t h) {
+  return _c->f_getTableForHash(_c, h);
+}
+
+static inline struct HvTable *ctx_getTableForName(HvBase *const _c, const char *tableName) {
+  return ctx_getTableForHash(_c, msg_symbolToHash(tableName));
+}
+
+/** Returns the total number of bytes allocated for this patch. */
+static inline unsigned int ctx_getNumBytes(HvBase *_c) {
+  return _c->numBytes;
+}
+
+#endif // _HEAVY_BASE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HvContext_bbb.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,215 @@
+
+/**
+ * Copyright (c) 2014,2015 Enzien Audio, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, and/or
+ * sublicense copies of the Software, strictly on a non-commercial basis,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * DO NOT MODIFY. THIS CODE IS MACHINE GENERATED BY THE SECTION6 HEAVY COMPILER.
+ */
+
+/*
+ * System Includes
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <string.h>
+#include <stdarg.h>
+#include "HvContext_bbb.h"
+#include "HeavyMath.h"
+
+
+/*
+ * Function Declarations
+ */
+
+
+
+/*
+ * Static Helper Functions
+ */
+
+static void ctx_intern_scheduleMessageForReceiver(
+    HvBase *const _c, const char *name, HvMessage *m) {
+  switch (msg_symbolToHash(name)) {
+    default: return;
+  }
+}
+
+static struct HvTable *ctx_intern_getTableForHash(HvBase *const _c, hv_uint32_t h) {
+  switch (h) {
+    default: return NULL;
+  }
+}
+
+
+
+/*
+ * Context Include and Implementatons
+ */
+
+Hv_bbb *hv_bbb_new_with_pool(double sampleRate, int poolKb) {
+  hv_assert(sampleRate > 0.0); // can't initialise with sampling rate of 0
+  hv_assert(poolKb >= 1); // a message pool of some reasonable size is always needed
+  Hv_bbb *const _c = (Hv_bbb *) hv_malloc(sizeof(Hv_bbb));
+
+  Base(_c)->numInputChannels = 0;
+  Base(_c)->numOutputChannels = 2;
+  Base(_c)->sampleRate = sampleRate;
+  Base(_c)->blockStartTimestamp = 0;
+  Base(_c)->f_scheduleMessageForReceiver = &ctx_intern_scheduleMessageForReceiver;
+  Base(_c)->f_getTableForHash = &ctx_intern_getTableForHash;
+  mq_initWithPoolSize(&Base(_c)->mq, poolKb);
+  Base(_c)->basePath = NULL;
+  Base(_c)->printHook = NULL;
+  Base(_c)->sendHook = NULL;
+  Base(_c)->userData = NULL;
+  Base(_c)->name = "bbb";
+
+  Base(_c)->numBytes = sizeof(Hv_bbb);
+  Base(_c)->numBytes += sPhasor_k_init(&_c->sPhasor_O587H, 440.0f, sampleRate);
+
+  // loadbang
+
+  return _c;
+}
+
+Hv_bbb *hv_bbb_new(double sampleRate) {
+  return hv_bbb_new_with_pool(sampleRate, 10); // default to 10KB MessagePool
+}
+
+void hv_bbb_free(Hv_bbb *_c) {
+
+  hv_free(Base(_c)->basePath);
+  mq_free(&Base(_c)->mq); // free queue after all objects have been freed, messages may be cancelled
+
+  hv_free(_c);
+}
+
+
+
+/*
+ * Static Function Implementation
+ */
+
+
+
+/*
+ * Context Process Implementation
+ */
+
+int hv_bbb_process(Hv_bbb *const _c, float **const inputBuffers, float **const outputBuffers, int nx) {
+  const int n4 = nx & ~HV_N_SIMD_MASK; // ensure that the block size is a multiple of HV_N_SIMD
+
+  // temporary signal vars
+  hv_bufferf_t Bf0, Bf1, Bf2, Bf3, Bf4;
+
+  // input and output vars
+  hv_bufferf_t O0, O1;
+
+  // declare and init the zero buffer
+  hv_bufferf_t ZERO; __hv_zero_f(VOf(ZERO));
+
+  hv_uint32_t nextBlock = Base(_c)->blockStartTimestamp;
+  for (int n = 0; n < n4; n += HV_N_SIMD) {
+
+    // process all of the messages for this block
+    nextBlock += HV_N_SIMD;
+    while (mq_hasMessageBefore(&Base(_c)->mq, nextBlock)) {
+      MessageNode *const node = mq_peek(&Base(_c)->mq);
+      node->sendMessage(Base(_c), node->let, node->m);
+      mq_pop(&Base(_c)->mq);
+    }
+
+    
+
+    // zero output buffers
+    __hv_zero_f(VOf(O0));
+    __hv_zero_f(VOf(O1));
+
+    // process all signal functions
+    __hv_phasor_k_f(&_c->sPhasor_O587H, VOf(Bf0));
+    __hv_var_k_f(VOf(Bf1), 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0);
+    __hv_sub_f(VIf(Bf0), VIf(Bf1), VOf(Bf1));
+    __hv_abs_f(VIf(Bf1), VOf(Bf1));
+    __hv_var_k_f(VOf(Bf0), 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0);
+    __hv_sub_f(VIf(Bf1), VIf(Bf0), VOf(Bf0));
+    __hv_var_k_f(VOf(Bf1), 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 0);
+    __hv_mul_f(VIf(Bf0), VIf(Bf1), VOf(Bf1));
+    __hv_mul_f(VIf(Bf1), VIf(Bf1), VOf(Bf0));
+    __hv_mul_f(VIf(Bf1), VIf(Bf0), VOf(Bf2));
+    __hv_mul_f(VIf(Bf2), VIf(Bf0), VOf(Bf0));
+    __hv_var_k_f(VOf(Bf3), 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0);
+    __hv_var_k_f(VOf(Bf4), 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0);
+    __hv_mul_f(VIf(Bf2), VIf(Bf4), VOf(Bf4));
+    __hv_sub_f(VIf(Bf1), VIf(Bf4), VOf(Bf4));
+    __hv_fma_f(VIf(Bf0), VIf(Bf3), VIf(Bf4), VOf(Bf4));
+    __hv_var_k_f(VOf(Bf3), 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0);
+    __hv_mul_f(VIf(Bf4), VIf(Bf3), VOf(Bf3));
+    __hv_add_f(VIf(Bf3), VIf(O1), VOf(O1));
+    __hv_add_f(VIf(Bf3), VIf(O0), VOf(O0));
+
+    // save output vars to output buffer
+    __hv_store_f(outputBuffers[0]+n, VIf(O0));
+    __hv_store_f(outputBuffers[1]+n, VIf(O1));
+  }
+
+  Base(_c)->blockStartTimestamp = nextBlock;
+
+  return n4; // return the number of frames processed
+}
+
+int hv_bbb_process_inline(Hv_bbb *c, float *const inputBuffers, float *const outputBuffers, int n4) {
+  hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD
+  int i = ctx_getNumInputChannels(Base(c));
+  float **bIn = (float **) hv_alloca(i*sizeof(float *));
+  while (i--) bIn[i] = inputBuffers+(i*n4);
+
+  i = ctx_getNumOutputChannels(Base(c));
+  float **bOut = (float **) hv_alloca(i*sizeof(float *));
+  while (i--) bOut[i] = outputBuffers+(i*n4);
+
+  int n = hv_bbb_process(c, bIn, bOut, n4);
+  return n;
+}
+
+int hv_bbb_process_inline_short(Hv_bbb *c, short *const inputBuffers, short *const outputBuffers, int n4) {
+  hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD
+  int numChannels = ctx_getNumInputChannels(Base(c));
+  float *bIn = (float *) hv_alloca(numChannels*n4*sizeof(float));
+  for (int i = 0; i < numChannels; ++i) {
+    for (int j = 0; j < n4; ++j) {
+      bIn[i*n4+j] = ((float) inputBuffers[i+numChannels*j]) * 0.00003051757813f;
+    }
+  }
+
+  numChannels = ctx_getNumOutputChannels(Base(c));
+  float *bOut = (float *) hv_alloca(numChannels*n4*sizeof(float));
+
+  int n = hv_bbb_process_inline(c, bIn, bOut, n4);
+
+  for (int i = 0; i < numChannels; ++i) {
+    for (int j = 0; j < n4; ++j) {
+      outputBuffers[i+numChannels*j] = (short) (bOut[i*n4+j] * 32767.0f);
+    }
+  }
+
+  return n;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HvContext_bbb.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,46 @@
+
+/**
+ * Copyright (c) 2014,2015 Enzien Audio, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, and/or
+ * sublicense copies of the Software, strictly on a non-commercial basis,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * DO NOT MODIFY. THIS CODE IS MACHINE GENERATED BY THE SECTION6 HEAVY COMPILER.
+ */
+
+#ifndef _HEAVYCONTEXT_BBB_H_
+#define _HEAVYCONTEXT_BBB_H_
+
+#include "HvBase.h"
+
+#define Context(_x) ((Hv_bbb *) (_x))
+
+// object includes
+#include "SignalVar.h"
+#include "SignalPhasor.h"
+#include "HeavyMath.h"
+
+typedef struct Hv_bbb {
+  HvBase base;
+
+  // objects
+  SignalPhasor sPhasor_O587H;
+} Hv_bbb;
+
+#endif // _HEAVYCONTEXT_BBB_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HvMessage.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,335 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "HvMessage.h"
+
+HvMessage *msg_init(HvMessage *m, hv_size_t numElements, hv_uint32_t timestamp) {
+  m->timestamp = timestamp;
+  m->numElements = (hv_uint16_t) numElements;
+  m->numBytes = (hv_uint16_t) msg_getByteSize(numElements);
+  return m;
+}
+
+HvMessage *msg_initWithFloat(HvMessage *m, hv_uint32_t timestamp, float f) {
+  m->timestamp = timestamp;
+  m->numElements = 1;
+  m->numBytes = sizeof(HvMessage);
+  msg_setFloat(m, 0, f);
+  return m;
+}
+
+HvMessage *msg_initWithBang(HvMessage *m, hv_uint32_t timestamp) {
+  m->timestamp = timestamp;
+  m->numElements = 1;
+  m->numBytes = sizeof(HvMessage);
+  msg_setBang(m, 0);
+  return m;
+}
+
+HvMessage *msg_initWithSymbol(HvMessage *m, hv_uint32_t timestamp, char *s) {
+  m->timestamp = timestamp;
+  m->numElements = 1;
+  m->numBytes = sizeof(HvMessage);
+  msg_setSymbol(m, 0, s);
+  return m;
+}
+
+HvMessage *msg_initWithHash(HvMessage *m, hv_uint32_t timestamp, hv_uint32_t h) {
+  m->timestamp = timestamp;
+  m->numElements = 1;
+  m->numBytes = sizeof(HvMessage);
+  msg_setHash(m, 0, h);
+  return m;
+}
+
+HvMessage *msg_initV(HvMessage *const m, const hv_uint32_t timestamp, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  const int numElem = (int) hv_strlen(format);
+  msg_init(m, numElem, timestamp);
+  for (int i = 0; i < numElem; i++) {
+    switch (format[i]) {
+      case 'b': msg_setBang(m,i); break;
+      case 'f': msg_setFloat(m, i, (float) va_arg(ap, double)); break;
+      case 's': msg_setSymbol(m, i, (char *) va_arg(ap, char *)); break;
+      case 'h': // hash not supported
+      default: break;
+    }
+  }
+  va_end(ap);
+
+  return m;
+}
+
+hv_size_t msg_getNumHeapBytes(const HvMessage *m) {
+  // get the size of all symbol elements
+  hv_size_t rsizeofsym = 0;
+  for (int i = 0; i < msg_getNumElements(m); ++i) {
+    if (msg_isSymbol(m,i)) {
+      rsizeofsym += (hv_size_t) hv_strlen(msg_getSymbol(m,i)) + 1; // +1 to allow for trailing '\0'
+    }
+  }
+
+  // the total byte size on the heap
+  return (msg_getByteSize(msg_getNumElements(m)) + rsizeofsym);
+}
+
+void msg_copyToBuffer(const HvMessage *m, char *buffer, hv_size_t len) {
+  HvMessage *r = (HvMessage *) buffer;
+
+  // assert that the message is not already larger than the length of the buffer
+  hv_assert(msg_getNumBytes(m) <= len);
+
+  // copy the basic message to the buffer
+  hv_memcpy(r, m, msg_getNumBytes(m));
+
+  hv_size_t len_r = msg_getNumBytes(m);
+
+  char *p = buffer + msg_getByteSize(msg_getNumElements(m)); // points to the end of the base message
+  for (int i = 0; i < msg_getNumElements(m); ++i) {
+    if (msg_isSymbol(m,i)) {
+      const hv_size_t symLen = (hv_size_t) hv_strlen(msg_getSymbol(m,i)) + 1; // include the trailing null char
+      hv_assert(len_r + symLen <= len); // stay safe!
+      hv_strncpy(p, msg_getSymbol(m,i), symLen);
+      msg_setSymbol(r, i, p);
+      p += symLen;
+      len_r += symLen;
+    }
+  }
+
+  r->numBytes = (hv_uint16_t) len_r; // update the message size in memory
+}
+
+// the message is serialised such that all symbol elements are placed in order at the end of the buffer
+HvMessage *msg_copy(const HvMessage *m) {
+  const hv_size_t heapSize = msg_getNumHeapBytes(m);
+  char *r = (char *) hv_malloc(heapSize);
+  msg_copyToBuffer(m, r, heapSize);
+  return (HvMessage *) r;
+}
+
+void msg_free(HvMessage *m) {
+  hv_free(m); // because heap messages are serialised in memory, a simple call to free releases the message
+}
+
+bool msg_hasFormat(const HvMessage *m, const char *fmt) {
+  if (fmt == NULL) return false;
+  if (msg_getNumElements(m) != hv_strlen(fmt)) return false;
+  for (int i = 0; i < msg_getNumElements(m); i++) {
+    switch (fmt[i]) {
+      case 'b': if (!msg_isBang(m, i)) return false; break;
+      case 'f': if (!msg_isFloat(m, i)) return false; break;
+      case 's': if (!msg_isSymbol(m, i)) return false; break;
+      case 'h': if (!msg_isHash(m, i)) return false; break;
+      default: return false;
+    }
+  }
+  return true;
+}
+
+bool msg_compareSymbol(const HvMessage *m, int i, const char *s) {
+  switch (msg_getType(m,i)) {
+    case SYMBOL: return !hv_strcmp(msg_getSymbol(m, i), s);
+    case HASH: return (msg_getHash(m,i) == msg_symbolToHash(s));
+    default: return false;
+  }
+}
+
+bool msg_equalsElement(const HvMessage *m, int i_m, const HvMessage *n, int i_n) {
+  if (i_m < msg_getNumElements(m) && i_n < msg_getNumElements(n)) {
+    if (msg_getType(m, i_m) == msg_getType(n, i_n)) {
+      switch (msg_getType(m, i_m)) {
+        case BANG: return true;
+        case FLOAT: return (msg_getFloat(m, i_m) == msg_getFloat(n, i_n));
+        case SYMBOL: return msg_compareSymbol(m, i_m, msg_getSymbol(n, i_n));
+        case HASH: return msg_getHash(m,i_m) == msg_getHash(n,i_n);
+        default: break;
+      }
+    }
+  }
+  return false;
+}
+
+void msg_setElementToFrom(HvMessage *n, int i_n, const HvMessage *const m, int i_m) {
+  switch (msg_getType(m, i_m)) {
+    case BANG: msg_setBang(n, i_n); break;
+    case FLOAT: msg_setFloat(n, i_n, msg_getFloat(m, i_m)); break;
+    case SYMBOL: msg_setSymbol(n, i_n, msg_getSymbol(m, i_m)); break;
+    case HASH: msg_setHash(n, i_n, msg_getHash(m, i_m));
+    default: break;
+  }
+}
+
+hv_uint32_t msg_symbolToHash(const char *s) {
+  // this hash is based MurmurHash2
+  // http://en.wikipedia.org/wiki/MurmurHash
+  // https://sites.google.com/site/murmurhash/
+  static const unsigned int n = 0x5bd1e995;
+  static const int r = 24;
+
+  int len = (int) hv_strlen(s);
+  hv_uint32_t x = (hv_uint32_t) (len); // seed (0) ^ len
+
+  while (len >= 4) {
+    hv_uint32_t k = *((hv_uint32_t *)s);
+    k *= n;
+    k ^= k >> r;
+    k *= n;
+    x *= n;
+    x ^= k;
+    s += 4; len -= 4;
+  }
+
+  switch(len) {
+    case 3: x ^= s[2] << 16;
+    case 2: x ^= s[1] << 8;
+    case 1: x ^= s[0]; x *= n;
+    default: break;
+  }
+
+  x ^= x >> 13;
+  x *= n;
+  x ^= x >> 15;
+
+  return x;
+}
+
+hv_uint32_t msg_getHash(const HvMessage *const m, int i) {
+  hv_assert(i < msg_getNumElements(m)); // invalid index
+  switch (msg_getType(m,i)) {
+    case BANG: return 0xFFFFFFFF;
+    case FLOAT: {
+      float f = msg_getFloat(m,i);
+      return *((hv_uint32_t *) &f);
+    }
+    case SYMBOL: return msg_symbolToHash(msg_getSymbol(m,i));
+    case HASH: return (&(m->elem)+i)->data.h;
+    default: return 0;
+  }
+}
+
+char *msg_toString(const HvMessage *m) {
+  hv_assert(msg_getNumElements(m) > 0);
+  int *len = (int *) hv_alloca(msg_getNumElements(m)*sizeof(int));
+  int size = 0; // the total length of our final buffer
+
+  // loop through every element in our list of atoms
+  // first loop figures out how long our buffer should be
+  for (int i = 0; i < msg_getNumElements(m); i++) {
+    // length of our string is each atom plus a space, or \0 on the end
+    switch (msg_getType(m, i)) {
+      case BANG: len[i] = hv_snprintf(NULL, 0, "%s", "bang") + 1; break;
+      case FLOAT: len[i] = hv_snprintf(NULL, 0, "%g", msg_getFloat(m, i)) + 1; break;
+      case SYMBOL: len[i] = hv_snprintf(NULL, 0, "%s", msg_getSymbol(m, i)) + 1; break;
+      case HASH: len[i] = hv_snprintf(NULL, 0, "0x%X", msg_getHash(m, i)) + 1; break;
+      default: break;
+    }
+    size += len[i];
+  }
+
+  hv_assert(size > 0);
+
+  // now we do the piecewise concatenation into our final string
+  // the final buffer we will pass back after concatenating all strings - user should free it
+  char *finalString = (char *) hv_malloc(size*sizeof(char));
+  int pos = 0;
+  for (int i = 0; i < msg_getNumElements(m); i++) {
+    // put a string representation of each atom into the final string
+    switch (msg_getType(m, i)) {
+      case BANG: hv_snprintf(finalString+pos, len[i], "%s", "bang"); break;
+      case FLOAT: hv_snprintf(finalString+pos, len[i], "%g", msg_getFloat(m, i)); break;
+      case SYMBOL: hv_snprintf(finalString+pos, len[i], "%s", msg_getSymbol(m, i)); break;
+      case HASH: hv_snprintf(finalString+pos, len[i], "0x%X", msg_getHash(m, i)); break;
+      default: break;
+    }
+    pos += len[i];
+    finalString[pos-1] = 32; // ASCII space
+  }
+  finalString[size-1] = '\0'; // ensure that the string is null terminated
+  return finalString;
+}
+
+/*
+ * TODO(mhroth): unnecessary for now
+bool msg_resolveDollarArguments(HvMessage *m, HvMessage *n, int z, char *buf, hv_size_t len, const char *args, ...) {
+  va_list ap;
+  va_start(ap, args);
+
+  hv_memset(buf, 0, len); // clear the buffer
+  hv_size_t j = 0; // position in buffer
+  const hv_size_t numArgs = hv_strlen(args); // the number of arguments
+
+  // if there is only one argument then the result has the chance of being a number, otherwise no
+  bool isNumber = (numArgs == 1);
+
+  for (hv_size_t i = 0; i < numArgs; ++i) {
+    switch (args[i]) {
+      case 'i': { // a message index
+        const int index = (int) va_arg(ap, int);
+        if (index < 0) {
+          // $0 always resolve to "0"
+          const hv_size_t x = 1;
+          if (x < len-j) { // always < in order to allow for trailing \0
+            j += snprintf(buf+j, len-j, "0");
+          }
+        } else {
+          switch (msg_getType(m, index)) {
+            default:
+            case BANG: break; // this case should never happen
+            case FLOAT: {
+              const hv_size_t x = snprintf(NULL, 0, "%g", msg_getFloat(m,index));
+              if (x < len-j) { // ensure that the buffer is big enough
+                j += snprintf(buf+j, len-j, "%g", msg_getFloat(m,index));
+              }
+              break;
+            }
+            case SYMBOL: {
+              const hv_size_t x = snprintf(NULL, 0, "%s", msg_getSymbol(m,index));
+              if (x < len-j) {
+                j += snprintf(buf+j, len-j, "%s", msg_getSymbol(m,index));
+                isNumber = false;
+              }
+              break;
+            }
+          }
+        }
+        break;
+      }
+      case 's': { // a string
+        const char *s = (char *) va_arg(ap, char *);
+        const hv_size_t x = snprintf(NULL, 0, "%s", s);
+        if (x <= len-j) {
+          j += snprintf(buf+j, len-j, "%s", s);
+          isNumber = false;
+        }
+        break;
+      }
+      default: break;
+    }
+  }
+
+  if (isNumber) {
+    msg_setFloat(n,z,(float) atof(buf));
+  } else {
+    msg_setSymbol(n,z,buf);
+  }
+
+  va_end(ap);
+
+  return !isNumber;
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HvMessage.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_MESSAGE_H_
+#define _HEAVY_MESSAGE_H_
+
+#include "Utils.h"
+
+typedef enum ElementType {
+  BANG,
+  FLOAT,
+  SYMBOL,
+  HASH
+} ElementType;
+
+typedef struct Element {
+  ElementType type;
+  union {
+    float f; // float
+    char *s; // symbol
+    hv_uint32_t h; // hash
+  } data;
+} Element;
+
+typedef struct HvMessage {
+  hv_uint32_t timestamp; // the sample at which this message should be processed
+  hv_uint16_t numElements;
+  hv_uint16_t numBytes; // the number of bytes that this message occupies in memory
+  Element elem;
+} HvMessage;
+
+#define HV_MESSAGE_ON_STACK(_x) (HvMessage *) hv_alloca(msg_getByteSize(_x))
+
+/** Returns the total length in bytes of this message for a given number of elements. */
+static inline hv_size_t msg_getByteSize(hv_size_t numElements) {
+  hv_assert(numElements > 0);
+  return sizeof(HvMessage) + ((numElements-1) * sizeof(Element));
+}
+
+HvMessage *msg_copy(const HvMessage *m);
+
+/** Returns the number of bytes that this message would occupy on the heap. */
+hv_size_t msg_getNumHeapBytes(const HvMessage *m);
+
+/** Copies the message into the given buffer. The buffer must be at least as large as msg_getNumHeapBytes(). */
+void msg_copyToBuffer(const HvMessage *m, char *buffer, hv_size_t len);
+
+void msg_setElementToFrom(HvMessage *n, int indexN, const HvMessage *const m, int indexM);
+
+/** Frees a message on the heap. Does nothing if argument is NULL. */
+void msg_free(HvMessage *m);
+
+HvMessage *msg_init(HvMessage *m, hv_size_t numElements, hv_uint32_t timestamp);
+
+HvMessage *msg_initWithFloat(HvMessage *m, hv_uint32_t timestamp, float f);
+
+HvMessage *msg_initWithBang(HvMessage *m, hv_uint32_t timestamp);
+
+HvMessage *msg_initWithSymbol(HvMessage *m, hv_uint32_t timestamp, char *s);
+
+HvMessage *msg_initWithHash(HvMessage *m, hv_uint32_t timestamp, hv_uint32_t h);
+
+HvMessage *msg_initV(HvMessage *const m, const hv_uint32_t timestamp, const char *format, ...);
+
+static inline hv_uint32_t msg_getTimestamp(const HvMessage *m) {
+  return m->timestamp;
+}
+
+static inline void msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp) {
+  m->timestamp = timestamp;
+}
+
+static inline int msg_getNumElements(const HvMessage *m) {
+  return (int) m->numElements;
+}
+
+/** Returns the number of bytes this message in memory. */
+static inline hv_size_t msg_getNumBytes(const HvMessage *m) {
+  return m->numBytes;
+}
+
+static inline ElementType msg_getType(const HvMessage *m, int index) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  return (&(m->elem)+index)->type;
+}
+
+static inline void msg_setBang(HvMessage *m, int index) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  (&(m->elem)+index)->type = BANG;
+  (&(m->elem)+index)->data.s = NULL;
+}
+
+static inline bool msg_isBang(const HvMessage *m, int index) {
+  return (index < msg_getNumElements(m)) ? (msg_getType(m,index) == BANG) : false;
+}
+
+static inline void msg_setFloat(HvMessage *m, int index, float f) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  (&(m->elem)+index)->type = FLOAT;
+  (&(m->elem)+index)->data.f = f;
+}
+
+static inline float msg_getFloat(const HvMessage *const m, int index) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  return (&(m->elem)+index)->data.f;
+}
+
+static inline bool msg_isFloat(const HvMessage *const m, int index) {
+  return (index < msg_getNumElements(m)) ? (msg_getType(m,index) == FLOAT) : false;
+}
+
+static inline void msg_setHash(HvMessage *m, int index, hv_uint32_t h) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  (&(m->elem)+index)->type = HASH;
+  (&(m->elem)+index)->data.h = h;
+}
+
+static inline bool msg_isHash(const HvMessage *m, int index) {
+  return (index < msg_getNumElements(m)) ? (msg_getType(m, index) == HASH) : false;
+}
+
+/** Returns true if the element is a hash or symbol. False otherwise. */
+static inline bool msg_isHashLike(const HvMessage *m, int index) {
+  return (index < msg_getNumElements(m)) ? ((msg_getType(m, index) == HASH) || (msg_getType(m, index) == SYMBOL)) : false;
+}
+
+/** Returns a 32-bit hash of the given string. */
+hv_uint32_t msg_symbolToHash(const char *s);
+
+/** Returns a 32-bit hash of the given element. */
+hv_uint32_t msg_getHash(const HvMessage *const m, int i);
+
+static inline void msg_setSymbol(HvMessage *m, int index, char *s) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  (&(m->elem)+index)->type = SYMBOL;
+  (&(m->elem)+index)->data.s = s;
+}
+
+static inline char *msg_getSymbol(const HvMessage *m, int index) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  return (&(m->elem)+index)->data.s;
+}
+
+static inline bool msg_isSymbol(const HvMessage *m, int index) {
+  return (index < msg_getNumElements(m)) ? (msg_getType(m, index) == SYMBOL) : false;
+}
+
+bool msg_compareSymbol(const HvMessage *m, int i, const char *s);
+
+/** Returns 1 if the element i_m of message m is equal to element i_n of message n. */
+bool msg_equalsElement(const HvMessage *m, int i_m, const HvMessage *n, int i_n);
+
+bool msg_hasFormat(const HvMessage *m, const char *fmt);
+
+/**
+ * Create a string representation of the message. Suitable for use by the print object.
+ * The resulting string must be freed by the caller.
+ */
+char *msg_toString(const HvMessage *msg);
+
+/**
+ * Resolves any number of dollar arguments and generates a string based on the arguments.
+ * @param m  The message from which to take values
+ * @param n  The message to fill in
+ * @param z  The element index to resolve
+ * @param buf  The scratch (i.e. resolution) buffer
+ * @param len  The length of the scratch buffer
+ * @param args  A string of 'i' and 's' chars indicating the type of the arguments, either indicies or strings
+ * @param varargs  The components to resolve, either dollar indicies or strings.
+ * If the index is negative, the graph id is used
+ * @return  true if the resolution buffer is needed, false otherwise.
+ */
+// bool msg_resolveDollarArguments(HvMessage *m, HvMessage *n, int z, char *buf, hv_size_t len, const char *args, ...);
+
+#endif // _HEAVY_MESSAGE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HvTable.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "HvTable.h"
+
+hv_size_t hTable_init(HvTable *o, int length) {
+  o->length = length;
+  // true size of the table is always an integer multple of HV_N_SIMD
+  o->size = (length + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
+  // add an extra length for mirroring
+  o->allocated = o->size + HV_N_SIMD;
+  o->head = 0;
+  hv_size_t numBytes = o->allocated * sizeof(float);
+  o->buffer = (float *) hv_malloc(numBytes);
+  hv_memset(o->buffer, numBytes);
+  return numBytes;
+}
+
+hv_size_t hTable_initWithData(HvTable *o, int length, const float *const data) {
+  o->length = length;
+  o->size = (length + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
+  o->allocated = o->size + HV_N_SIMD;
+  o->head = 0;
+  hv_size_t numBytes = o->size * sizeof(float);
+  o->buffer = (float *) hv_malloc(numBytes);
+  hv_memset(o->buffer, numBytes);
+  hv_memcpy(o->buffer, data, length*sizeof(float));
+  return numBytes;
+}
+
+hv_size_t hTable_initWithFinalData(HvTable *o, int length, float *data) {
+  o->length = length;
+  o->size = length;
+  o->allocated = length;
+  o->buffer = data;
+  o->head = 0;
+  return 0;
+}
+
+void hTable_free(HvTable *o) {
+  hv_free(o->buffer);
+}
+
+int hTable_resize(HvTable *o, hv_uint32_t newLength) {
+  // TODO(mhroth): update context with memory allocated by table
+  // NOTE(mhroth): mirrored bytes are not necessarily carried over
+  const hv_uint32_t oldBytes = (hv_uint32_t) (o->size * sizeof(float));
+  const hv_uint32_t newSize = (newLength + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
+  const hv_uint32_t newAllocated = newSize + HV_N_SIMD;
+  const hv_uint32_t newBytes = (hv_uint32_t) (newAllocated * sizeof(float));
+  float *b = (float *) hv_realloc(o->buffer, newBytes);
+  hv_assert(b != NULL); // error while reallocing!
+  if (newSize > o->size) hv_clear_buffer(b+o->size, newAllocated-o->size); // clear new parts of the buffer
+  if (b != o->buffer) {
+    // the buffer has been reallocated, ensure that it is on a 32-byte boundary
+    if ((((uintptr_t) (const void *) b) & 0x10) == 0) {
+      o->buffer = b;
+    } else {
+      float *c = (float *) hv_malloc(newBytes);
+      hv_assert(c != NULL);
+      hv_clear_buffer(c, newLength);
+      const hv_size_t min = hv_min_ui(o->size, newLength);
+      hv_memcpy(c, b, min * sizeof(float));
+      hv_free(b);
+      o->buffer = c;
+    }
+  }
+  o->length = newLength;
+  o->size = newSize;
+  o->allocated = newAllocated;
+  return (int) (newBytes - oldBytes);
+}
+
+void hTable_onMessage(HvBase *_c, HvTable *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+  if (msg_compareSymbol(m,0,"resize") && msg_isFloat(m,1) && msg_getFloat(m,1) >= 0.0f) {
+    hTable_resize(o, (int) hv_ceil_f(msg_getFloat(m,1))); // apply ceil to ensure that tables always have enough space
+
+    // send out the new size of the table
+    HvMessage *n = HV_MESSAGE_ON_STACK(1);
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getSize(o));
+    sendMessage(_c, 0, n);
+  }
+
+  else if (msg_compareSymbol(m,0,"mirror")) {
+    hv_memcpy(o->buffer+o->size, o->buffer, HV_N_SIMD*sizeof(float));
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/HvTable.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_TABLE_H_
+#define _HEAVY_TABLE_H_
+
+#include "HvBase.h"
+#include "HvMessage.h"
+#include "Utils.h"
+
+typedef struct HvTable {
+  float *buffer;
+  // the number of values that the table is requested to have
+  hv_uint32_t length;
+
+  // the number of usable values that the table actually has
+  // this is always an even multiple of HV_N_SIMD
+  hv_uint32_t size;
+
+  // Note that the true size of the table is (size + HV_N_SIMD),
+  // with the trailing values used by the system, e.g. to create a circular
+  // buffer
+  hv_uint32_t allocated;
+
+  hv_uint32_t head; // the most recently written point
+} HvTable;
+
+hv_size_t hTable_init(HvTable *o, int length);
+
+hv_size_t hTable_initWithData(HvTable *o, int length, const float *const data);
+
+hv_size_t hTable_initWithFinalData(HvTable *o, int length, float *data);
+
+void hTable_free(HvTable *o);
+
+int hTable_resize(HvTable *o, hv_uint32_t newLength);
+
+void hTable_onMessage(HvBase *_c, HvTable *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+static inline float *hTable_getBuffer(HvTable *o) {
+  return o->buffer;
+}
+
+// the user-requested length of the table (number of floats)
+static inline hv_uint32_t hTable_getLength(HvTable *o) {
+  return o->length;
+}
+
+// the usable length of the table (an even multiple of HV_N_SIMD)
+static inline hv_uint32_t hTable_getSize(HvTable *o) {
+  return o->size;
+}
+
+// the number of floats allocated to this table (usually size + HV_N_SIMD)
+static inline hv_uint32_t hTable_getAllocated(HvTable *o) {
+  return o->allocated;
+}
+
+static inline hv_uint32_t hTable_getHead(HvTable *o) {
+  return o->head;
+}
+
+static inline void hTable_setHead(HvTable *o, hv_uint32_t head) {
+  o->head = head;
+}
+
+#endif // _HEAVY_TABLE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/MessagePool.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,141 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "MessagePool.h"
+#include "HvMessage.h"
+#include "Utils.h"
+
+// the number of bytes reserved at a time from the pool
+#define MP_BLOCK_SIZE_BYTES 512
+
+#if HV_APPLE
+#pragma mark - MessageList
+#endif
+
+typedef struct MessageListNode {
+  char *p;
+  struct MessageListNode *next;
+} MessageListNode;
+
+static inline bool ml_hasAvailable(MessagePoolList *ml) {
+  return (ml->head != NULL);
+}
+
+static char *ml_pop(MessagePoolList *ml) {
+  MessageListNode *n = ml->head;
+  ml->head = n->next;
+  n->next = ml->pool;
+  ml->pool = n;
+  char *const p = n->p;
+  n->p = NULL; // set to NULL to make it clear that this node does not have a valid buffer
+  return p;
+}
+
+/** Push a MessageListNode with the given pointer onto the head of the queue. */
+static void ml_push(MessagePoolList *ml, void *p) {
+  MessageListNode *n = NULL;
+  if (ml->pool != NULL) {
+    // take an empty MessageListNode from the pool
+    n = ml->pool;
+    ml->pool = n->next;
+  } else {
+    // a MessageListNode is not available, allocate one
+    n = (MessageListNode *) hv_malloc(sizeof(MessageListNode));
+  }
+  n->p = (char *) p;
+  n->next = ml->head;
+  ml->head = n; // push to the front of the queue
+}
+
+static void ml_free(MessagePoolList *ml) {
+  if (ml != NULL) {
+    while (ml_hasAvailable(ml)) {
+      ml_pop(ml);
+    }
+    while (ml->pool != NULL) {
+      MessageListNode *n = ml->pool;
+      ml->pool = n->next;
+      hv_free(n);
+    }
+  }
+}
+
+#if HV_APPLE
+#pragma mark - MessagePool
+#endif
+
+static hv_size_t mp_messagelistIndexForSize(hv_size_t byteSize) {
+  return (hv_size_t) hv_max_i((hv_min_max_log2((hv_uint32_t) byteSize) - 5), 0);
+}
+
+hv_size_t mp_init(MessagePool *mp, hv_size_t numKB) {
+  mp->bufferSize = numKB * 1024;
+  mp->buffer = (char *) hv_malloc(mp->bufferSize);
+  mp->bufferIndex = 0;
+
+  // initialise all message lists
+  for (int i = 0; i < MP_NUM_MESSAGE_LISTS; i++) {
+    mp->lists[i].head = NULL;
+    mp->lists[i].pool = NULL;
+  }
+
+  return mp->bufferSize;
+}
+
+void mp_free(MessagePool *mp) {
+  hv_free(mp->buffer);
+  for (int i = 0; i < MP_NUM_MESSAGE_LISTS; i++) {
+    ml_free(&mp->lists[i]);
+  }
+}
+
+void mp_freeMessage(MessagePool *mp, HvMessage *m) {
+  const hv_size_t b = msg_getNumBytes(m); // the number of bytes that a message occupies in memory
+  const hv_size_t i = mp_messagelistIndexForSize(b); // the MessagePoolList index in the pool
+  MessagePoolList *ml = &mp->lists[i];
+  const hv_size_t chunkSize = 32 << i;
+  hv_memset(m, chunkSize); // clear the chunk, just in case
+  ml_push(ml, m);
+}
+
+HvMessage *mp_addMessage(MessagePool *mp, const HvMessage *m) {
+  const hv_size_t b = msg_getNumHeapBytes(m);
+  // determine the message list index to allocate data from based on the msg size
+  // smallest chunk size is 32 bytes
+  const hv_size_t i = mp_messagelistIndexForSize(b);
+
+  assert(i < MP_NUM_MESSAGE_LISTS); // how many chunk sizes do we want to support? 32, 64, 128, 256 at the moment
+  MessagePoolList *ml = &mp->lists[i];
+  const hv_size_t chunkSize = 32 << i;
+
+  if (ml_hasAvailable(ml)) {
+    char *buf = ml_pop(ml);
+    msg_copyToBuffer(m, buf, chunkSize);
+    return (HvMessage *) buf;
+  } else {
+    // if no appropriately sized buffer is immediately available, increase the size of the used buffer
+    const hv_size_t newIndex = mp->bufferIndex + MP_BLOCK_SIZE_BYTES;
+    hv_assert(newIndex <= mp->bufferSize); // have we have exceeded the buffer size?
+
+    for (hv_size_t i = mp->bufferIndex; i < newIndex; i += chunkSize) {
+      ml_push(ml, mp->buffer + i); // push new nodes onto the list with chunk pointers
+    }
+    mp->bufferIndex = newIndex;
+    char *buf = ml_pop(ml);
+    msg_copyToBuffer(m, buf, chunkSize);
+    return (HvMessage *) buf;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/MessagePool.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MESSAGE_POOL_H_
+#define _MESSAGE_POOL_H_
+
+#include "Utils.h"
+
+struct HvMessage;
+
+#define MP_NUM_MESSAGE_LISTS 4
+
+typedef struct MessagePoolList {
+  struct MessageListNode *head; // list of currently available blocks
+  struct MessageListNode *pool; // list of currently used blocks
+} MessagePoolList;
+
+typedef struct MessagePool {
+  char *buffer; // the buffer of all messages
+  hv_size_t bufferSize; // in bytes
+  hv_size_t bufferIndex; // the number of total reserved bytes
+
+  MessagePoolList lists[MP_NUM_MESSAGE_LISTS];
+} MessagePool;
+
+/**
+ * The MessagePool is a basic memory management system. It reserves a large block of memory at initialisation
+ * and proceeds to divide this block into smaller chunks (usually 512 bytes) as they are needed. These chunks are
+ * further divided into 32, 64, 128, or 256 sections. Each of these sections is managed by a MessagePoolList (MPL).
+ * An MPL is a linked-list data structure which is initialised such that its own pool of listnodes is filled with nodes
+ * that point at each subblock (e.g. each 32-byte block of a 512-block chunk).
+ *
+ * MessagePool is loosely inspired by TCMalloc. http://goog-perftools.sourceforge.net/doc/tcmalloc.html
+ */
+
+hv_size_t mp_init(struct MessagePool *mp, hv_size_t numKB);
+
+void mp_free(struct MessagePool *mp);
+
+/**
+ * Adds a message to the pool and returns a pointer to the copy. Returns NULL
+ * if no space was available in the pool.
+ */
+struct HvMessage *mp_addMessage(struct MessagePool *mp, const struct HvMessage *m);
+
+void mp_freeMessage(struct MessagePool *mp, struct HvMessage *m);
+
+#endif // _MESSAGE_POOL_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/MessageQueue.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,218 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "MessageQueue.h"
+#include "Utils.h"
+
+hv_size_t mq_init(MessageQueue *q) {
+  q->head = NULL;
+  q->tail = NULL;
+  q->pool = NULL;
+  return mp_init(&q->mp, 1);
+}
+
+void mq_initWithPoolSize(MessageQueue *q, hv_size_t poolSizeKB) {
+  q->head = NULL;
+  q->tail = NULL;
+  q->pool = NULL;
+  mp_init(&q->mp, poolSizeKB);
+}
+
+void mq_free(MessageQueue *q) {
+  mq_clear(q);
+  while (q->pool != NULL) {
+    MessageNode *n = q->pool;
+    q->pool = q->pool->next;
+    hv_free(n);
+  }
+  mp_free(&q->mp);
+}
+
+static MessageNode *mq_getOrCreateNodeFromPool(MessageQueue *q) {
+  if (q->pool == NULL) {
+    // if necessary, create a new empty node
+    q->pool = (MessageNode *) hv_malloc(sizeof(MessageNode));
+    q->pool->next = NULL;
+  }
+  MessageNode *node = q->pool;
+  q->pool = q->pool->next;
+  return node;
+}
+
+int mq_size(MessageQueue *q) {
+    int size = 0;
+    MessageNode *n = q->head;
+    while (n != NULL) {
+        ++size;
+        n = n->next;
+    }
+    return size;
+}
+
+HvMessage *mq_addMessage(MessageQueue *q, const HvMessage *m, int let,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *)) {
+  MessageNode *node = mq_getOrCreateNodeFromPool(q);
+  node->m = mp_addMessage(&q->mp, m);
+  node->let = let;
+  node->sendMessage = sendMessage;
+  node->prev = NULL;
+  node->next = NULL;
+
+  if (q->tail != NULL) {
+    // the list already contains elements
+    q->tail->next = node;
+    node->prev = q->tail;
+    q->tail = node;
+  } else {
+    // the list is empty
+    node->prev = NULL;
+    q->head = node;
+    q->tail = node;
+  }
+  return mq_node_getMessage(node);
+}
+
+HvMessage *mq_addMessageByTimestamp(MessageQueue *q, HvMessage *m, int let,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *)) {
+  if (mq_hasMessage(q)) {
+    MessageNode *n = mq_getOrCreateNodeFromPool(q);
+    n->m = mp_addMessage(&q->mp, m);
+    n->let = let;
+    n->sendMessage = sendMessage;
+
+    if (msg_getTimestamp(m) < msg_getTimestamp(q->head->m)) {
+      // the message occurs before the current head
+      n->next = q->head;
+      q->head->prev = n;
+      n->prev = NULL;
+      q->head = n;
+    } else if (msg_getTimestamp(m) >= msg_getTimestamp(q->tail->m)) {
+      // the message occurs after the current tail
+      n->next = NULL;
+      n->prev = q->tail;
+      q->tail->next = n;
+      q->tail = n;
+    } else {
+      // the message occurs somewhere between the head and tail
+      MessageNode *node = q->head;
+      while (node != NULL) {
+        if (m->timestamp < msg_getTimestamp(node->next->m)) {
+          MessageNode *r = node->next;
+          node->next = n;
+          n->next = r;
+          n->prev = node;
+          r->prev = n;
+          break;
+        }
+        node = node->next;
+      }
+    }
+    return n->m;
+  } else {
+    // add a message to the head
+    return mq_addMessage(q, m, let, sendMessage);
+  }
+}
+
+void mq_pop(MessageQueue *q) {
+  if (mq_hasMessage(q)) {
+    MessageNode *n = q->head;
+
+    mp_freeMessage(&q->mp, n->m);
+    n->m = NULL;
+
+    n->let = 0;
+    n->sendMessage = NULL;
+
+    q->head = n->next;
+    if (q->head == NULL) {
+      q->tail = NULL;
+    } else {
+      q->head->prev = NULL;
+    }
+    n->next = q->pool;
+    n->prev = NULL;
+    q->pool = n;
+  }
+}
+
+void mq_removeMessage(MessageQueue *q, HvMessage *m, void (*sendMessage)(struct HvBase *, int, const HvMessage *)) {
+  if (mq_hasMessage(q)) {
+    if (mq_node_getMessage(q->head) == m) { // msg in head node
+      // only remove the message if sendMessage is the same as the stored one,
+      // if the sendMessage argument is NULL, it is not checked and will remove any matching message pointer
+      if (sendMessage == NULL || q->head->sendMessage == sendMessage) {
+        mq_pop(q);
+      }
+    } else {
+      MessageNode *prevNode = q->head;
+      MessageNode *currNode = q->head->next;
+      while ((currNode != NULL) && (currNode->m != m)) {
+        prevNode = currNode;
+        currNode = currNode->next;
+      }
+      if (currNode != NULL) {
+        if (sendMessage == NULL || currNode->sendMessage == sendMessage) {
+          mp_freeMessage(&q->mp, m);
+          currNode->m = NULL;
+          currNode->let = 0;
+          currNode->sendMessage = NULL;
+          if (currNode == q->tail) { // msg in tail node
+            prevNode->next = NULL;
+            q->tail = prevNode;
+          } else { // msg in middle node
+            prevNode->next = currNode->next;
+            currNode->next->prev = prevNode;
+          }
+          currNode->next = (q->pool == NULL) ? NULL : q->pool;
+          currNode->prev = NULL;
+          q->pool = currNode;
+        }
+      }
+    }
+  }
+}
+
+void mq_clear(MessageQueue *q) {
+  while (mq_hasMessage(q)) {
+    mq_pop(q);
+  }
+}
+
+void mq_clearAfter(MessageQueue *q, const double timestamp) {
+  MessageNode *n = q->tail;
+  while (n != NULL && timestamp <= msg_getTimestamp(n->m)) {
+    // free the node's message
+    mp_freeMessage(&q->mp, n->m);
+    n->m = NULL;
+    n->let = 0;
+    n->sendMessage = NULL;
+
+    // the tail points at the previous node
+    q->tail = n->prev;
+
+    // put the node back in the pool
+    n->next = q->pool;
+    n->prev = NULL;
+    if (q->pool != NULL) q->pool->prev = n;
+    q->pool = n;
+
+    // update the tail node
+    n = q->tail;
+  }
+
+  if (q->tail == NULL) q->head = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/MessageQueue.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MESSAGE_QUEUE_H_
+#define _MESSAGE_QUEUE_H_
+
+#include "HvMessage.h"
+#include "MessagePool.h"
+
+struct HvBase;
+
+typedef struct MessageNode {
+  struct MessageNode *prev; // doubly linked list
+  struct MessageNode *next;
+  HvMessage *m;
+  void (*sendMessage)(struct HvBase *, int, const HvMessage *);
+  int let;
+} MessageNode;
+
+/** A doubly linked list containing scheduled messages. */
+typedef struct MessageQueue {
+  MessageNode *head; // the head of the queue
+  MessageNode *tail; // the tail of the queue
+  MessageNode *pool; // the head of the reserve pool
+  MessagePool mp;
+} MessageQueue;
+
+hv_size_t mq_init(MessageQueue *q);
+
+void mq_initWithPoolSize(MessageQueue *q, hv_size_t poolSizeKB);
+
+void mq_free(MessageQueue *q);
+
+int mq_size(MessageQueue *q);
+
+static inline HvMessage *mq_node_getMessage(MessageNode *n) {
+  return n->m;
+}
+
+static inline int mq_node_getLet(MessageNode *n) {
+  return n->let;
+}
+
+static inline bool mq_hasMessage(MessageQueue *q) {
+  return (q->head != NULL);
+}
+
+// true if there is a message and it occurs before (<) timestamp
+static inline bool mq_hasMessageBefore(MessageQueue *const q, const hv_uint32_t timestamp) {
+  return mq_hasMessage(q) && (msg_getTimestamp(mq_node_getMessage(q->head)) < timestamp);
+}
+
+static inline MessageNode *mq_peek(MessageQueue *q) {
+  return q->head;
+}
+
+/** Appends the message to the end of the queue. */
+HvMessage *mq_addMessage(MessageQueue *q, const HvMessage *m, int let,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *));
+
+/** Insert in ascending order the message acccording to its timestamp. */
+HvMessage *mq_addMessageByTimestamp(MessageQueue *q, HvMessage *m, int let,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *));
+
+/** Pop the message at the head of the queue (and free its memory). */
+void mq_pop(MessageQueue *q);
+
+/** Remove a message from the queue (and free its memory) */
+void mq_removeMessage(MessageQueue *q, HvMessage *m,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *));
+
+/** Clears (and frees) all messages in the queue. */
+void mq_clear(MessageQueue *q);
+
+/** Removes all messages occuring at or after the given timestamp. */
+void mq_clearAfter(MessageQueue *q, const double timestamp);
+
+#endif // _MESSAGE_QUEUE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalDel1.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalDel1.h"
+
+hv_size_t sDel1_init(SignalDel1 *o) {
+#if HV_SIMD_AVX
+  o->x = _mm256_setzero_ps();
+#elif HV_SIMD_SSE
+  o->x = _mm_setzero_ps();
+#elif HV_SIMD_NEON
+  o->x = vdupq_n_f32(0.0f);
+#else
+  o->x = 0.0f;
+#endif
+  return 0;
+}
+
+void sDel1_onMessage(HvBase *_c, SignalDel1 *o, int letIn, const HvMessage *m) {
+  if (letIn == 2) {
+    if (msg_compareSymbol(m, 0, "clear")) {
+#if HV_SIMD_AVX
+      o->x = _mm256_setzero_ps();
+#elif HV_SIMD_SSE
+      o->x = _mm_setzero_ps();
+#elif HV_SIMD_NEON
+      o->x = vdupq_n_f32(0.0f);
+#else
+      o->x = 0.0f;
+#endif
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalDel1.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SIGNAL_DEL1_H_
+#define _SIGNAL_DEL1_H_
+
+#include "HvBase.h"
+
+typedef struct SignalDel1 {
+  hv_bufferf_t x;
+} SignalDel1;
+
+hv_size_t sDel1_init(SignalDel1 *o);
+
+void sDel1_onMessage(HvBase *_c, SignalDel1 *o, int letIn, const HvMessage *m);
+
+static inline void __hv_del1_f(SignalDel1 *o, hv_bInf_t bIn0, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  __m256 x = _mm256_permute_ps(bIn0, _MM_SHUFFLE(2,1,0,3)); // [3 0 1 2 7 4 5 6]
+  __m256 n = _mm256_permute2f128_ps(o->x,x,0x1);            // [h e f g 3 0 1 2]
+  *bOut = _mm256_blend_ps(x, n, 0x11);                      // [g 0 1 2 3 4 5 6]
+  o->x = x;
+#elif HV_SIMD_SSE
+  __m128 n = _mm_blend_ps(o->x, bIn0, 0x7);
+  *bOut = _mm_shuffle_ps(n, n, _MM_SHUFFLE(2,1,0,3));
+  o->x = bIn0;
+#elif HV_SIMD_NEON
+  *bOut = vextq_f32(o->x, bIn0, 3);
+  o->x = bIn0;
+#else
+  *bOut = o->x;
+  o->x = bIn0;
+#endif
+}
+
+#endif // _SIGNAL_DEL1_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalPhasor.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalPhasor.h"
+
+// input phase is in the range of [0,1]. It is independent of o->phase.
+#if HV_SIMD_AVX
+static void sPhasor_updatePhase(SignalPhasor *o, float p) {
+  o->phase = _mm256_set_ps(
+      p+1.0f+7.0f*o->step.f2sc, p+1.0f+6.0f*o->step.f2sc,
+      p+1.0f+5.0f*o->step.f2sc, p+1.0f+4.0f*o->step.f2sc,
+      p+1.0f+3.0f*o->step.f2sc, p+1.0f+2.0f*o->step.f2sc,
+      p+1.0f+o->step.f2sc,      p+1.0f);
+
+  // ensure that o->phase is still in range [1,2]
+  o->phase = _mm256_or_ps(_mm256_andnot_ps(
+      _mm256_set1_ps(-INFINITY), o->phase), _mm256_set1_ps(1.0f));
+#elif HV_SIMD_SSE
+static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) {
+  o->phase = _mm_set_epi32(3*o->step.s+p, 2*o->step.s+p, o->step.s+p, p);
+#elif HV_SIMD_NEON
+static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) {
+  o->phase = (uint32x4_t) {p, o->step.s+p, 2*o->step.s+p, 3*o->step.s+p};
+#else // HV_SIMD_NONE
+static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) {
+  o->phase = p;
+#endif
+}
+
+static void sPhasor_updateFrequency(SignalPhasor *o, float f, double r) {
+#if HV_SIMD_AVX
+  o->step.f2sc = (float) (f/r);
+  o->inc = _mm256_set1_ps((float) (8.0f*f/r));
+  sPhasor_updatePhase(o, o->phase[0]);
+#elif HV_SIMD_SSE
+  o->step.s = (hv_int32_t) (f*(4294967296.0/r));
+  o->inc = _mm_set1_epi32(4*o->step.s);
+  sPhasor_updatePhase(o, (hv_uint32_t) (o->phase[0] & 0xFFFFFFFFL));
+#elif HV_SIMD_NEON
+  o->step.s = (hv_int32_t) (f*(4294967296.0/r));
+  o->inc = vdupq_n_s32(4*o->step.s);
+  sPhasor_updatePhase(o, vgetq_lane_u32(o->phase, 0));
+#else // HV_SIMD_NONE
+  o->step.s = (hv_int32_t) (f*(4294967296.0/r));
+  o->inc = o->step.s;
+  // no need to update phase
+#endif
+}
+
+hv_size_t sPhasor_init(SignalPhasor *o, double samplerate) {
+#if HV_SIMD_AVX
+  o->phase = _mm256_set1_ps(1.0f);
+  o->inc = _mm256_setzero_ps();
+  o->step.f2sc = (float) (1.0/samplerate);
+#elif HV_SIMD_SSE
+  o->phase = _mm_setzero_si128();
+  o->inc = _mm_setzero_si128();
+  o->step.f2sc = (float) (4294967296.0/samplerate);
+#elif HV_SIMD_NEON
+  o->phase = vdupq_n_u32(0);
+  o->inc = vdupq_n_s32(0);
+  o->step.f2sc = (float) (4294967296.0/samplerate);
+#else // HV_SIMD_NONE
+  o->phase = 0;
+  o->inc = 0;
+  o->step.f2sc = (float) (4294967296.0/samplerate);
+#endif
+  return 0;
+}
+
+void sPhasor_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m) {
+  if (letIn == 1) {
+    if (msg_isFloat(m,0)) {
+      float phase = msg_getFloat(m,0);
+      while (phase < 0.0f) phase += 1.0f; // wrap phase to [0,1]
+      while (phase > 1.0f) phase -= 1.0f;
+#if HV_SIMD_AVX
+      sPhasor_updatePhase(o, phase);
+#else // HV_SIMD_SSE || HV_SIMD_NEON || HV_SIMD_NONE
+      sPhasor_updatePhase(o, (hv_int32_t) (phase * 4294967296.0));
+#endif
+    }
+  }
+}
+
+hv_size_t sPhasor_k_init(SignalPhasor *o, float frequency, double samplerate) {
+  sPhasor_updateFrequency(o, frequency, samplerate);
+  sPhasor_updatePhase(o, 0);
+  return 0;
+}
+
+void sPhasor_k_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m) {
+  if (msg_isFloat(m,0)) {
+    switch (letIn) {
+      case 0: sPhasor_updateFrequency(o, msg_getFloat(m,0), ctx_getSampleRate(_c)); break;
+      case 1: {
+        float phase = msg_getFloat(m,0);
+        while (phase < 0.0f) phase += 1.0f; // wrap phase to [0,1]
+        while (phase > 1.0f) phase -= 1.0f;
+#if HV_SIMD_AVX
+        sPhasor_updatePhase(o, phase);
+#else // HV_SIMD_SSE || HV_SIMD_NEON || HV_SIMD_NONE
+        sPhasor_updatePhase(o, (hv_uint32_t) (phase * 4294967296.0));
+#endif
+        break;
+      }
+      default: break;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalPhasor.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,131 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_SIGNAL_PHASOR_H_
+#define _HEAVY_SIGNAL_PHASOR_H_
+
+#include "HvBase.h"
+
+typedef struct SignalPhasor {
+#if HV_SIMD_AVX
+  __m256 phase; // current phase
+  __m256 inc;   // phase increment
+#elif HV_SIMD_SSE
+  __m128i phase;
+  __m128i inc;
+#elif HV_SIMD_NEON
+  uint32x4_t phase;
+  int32x4_t inc;
+#else // HV_SIMD_NONE
+  hv_uint32_t phase;
+  hv_int32_t inc;
+#endif
+  union {
+    float f2sc; // float to step conversion (used for __phasor~f)
+    hv_int32_t s; // step value (used for __phasor_k~f)
+  } step;
+} SignalPhasor;
+
+hv_size_t sPhasor_init(SignalPhasor *o, double samplerate);
+
+hv_size_t sPhasor_k_init(SignalPhasor *o, float frequency, double samplerate);
+
+void sPhasor_k_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m);
+
+void sPhasor_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m);
+
+static inline void __hv_phasor_f(SignalPhasor *o, hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  __m256 p = _mm256_mul_ps(bIn, _mm256_set1_ps(o->step.f2sc)); // a b c d e f g h
+
+  __m256 z = _mm256_setzero_ps();
+
+  // http://stackoverflow.com/questions/11906814/how-to-rotate-an-sse-avx-vector
+  __m256 a = _mm256_permute_ps(p, _MM_SHUFFLE(2,1,0,3)); // d a b c h e f g
+  __m256 b = _mm256_permute2f128_ps(a, a, 0x01);         // h e f g d a b c
+  __m256 c = _mm256_blend_ps(a, b, 0x10);                // d a b c d e f g
+  __m256 d = _mm256_blend_ps(c, z, 0x01);                // 0 a b c d e f g
+  __m256 e = _mm256_add_ps(p, d); // a (a+b) (b+c) (c+d) (d+e) (e+f) (f+g) (g+h)
+
+  __m256 f = _mm256_permute_ps(e, _MM_SHUFFLE(1,0,3,2)); // (b+c) (c+d) a (a+b) (f+g) (g+h) (d+e) (e+f)
+  __m256 g = _mm256_permute2f128_ps(f, f, 0x01);         // (f+g) (g+h) (d+e) (e+f) (b+c) (c+d) a (a+b)
+  __m256 h = _mm256_blend_ps(f, g, 0x33);                // (b+c) (c+d) a (a+b) (b+c) (c+d) (d+e) (e+f)
+  __m256 i = _mm256_blend_ps(h, z, 0x03);                // 0 0 a (a+b) (b+c) (c+d) (d+e) (e+f)
+  __m256 j = _mm256_add_ps(e, i); // a (a+b) (a+b+c) (a+b+c+d) (b+c+d+e) (c+d+e+f) (d+e+f+g) (e+f+g+h)
+
+  __m256 k = _mm256_permute2f128_ps(j, z, 0x02);         // 0 0 0 0 a (a+b) (a+b+c) (a+b+c+d) (b+c+d+e)
+  __m256 m = _mm256_add_ps(j, k); // a (a+b) (a+b+c) (a+b+c+d) (a+b+c+d+e) (a+b+c+d+e+f) (a+b+c+d+e+f+g) (a+b+c+d+e+f+g+h)
+
+  __m256 n = _mm256_or_ps(_mm256_andnot_ps(
+      _mm256_set1_ps(-INFINITY),
+      _mm256_add_ps(o->phase, m)),
+      _mm256_set1_ps(1.0f));
+
+  *bOut = _mm256_sub_ps(n, _mm256_set1_ps(1.0f));
+
+  __m256 x = _mm256_permute_ps(n, _MM_SHUFFLE(3,3,3,3));
+  o->phase = _mm256_permute2f128_ps(x, x, 0x11);
+#elif HV_SIMD_SSE
+  __m128i p = _mm_cvtps_epi32(_mm_mul_ps(bIn, _mm_set1_ps(o->step.f2sc))); // convert frequency to step
+  p = _mm_add_epi32(p, _mm_slli_si128(p, 4)); // add incremental steps to phase (prefix sum)
+  p = _mm_add_epi32(p, _mm_slli_si128(p, 8)); // http://stackoverflow.com/questions/10587598/simd-prefix-sum-on-intel-cpu?rq=1
+  p = _mm_add_epi32(o->phase, p);
+  *bOut = _mm_sub_ps(_mm_castsi128_ps(
+      _mm_or_si128(_mm_srli_epi32(p, 9),
+      (__m128i) {0x3F8000003F800000L, 0x3F8000003F800000L})),
+      _mm_set1_ps(1.0f));
+  o->phase = _mm_shuffle_epi32(p, _MM_SHUFFLE(3,3,3,3));
+#elif HV_SIMD_NEON
+  int32x4_t p = vcvtq_s32_f32(vmulq_n_f32(bIn, o->step.f2sc));
+  p = vaddq_s32(p, vextq_s32(vdupq_n_s32(0), p, 3)); // http://stackoverflow.com/questions/11259596/arm-neon-intrinsics-rotation
+  p = vaddq_s32(p, vextq_s32(vdupq_n_s32(0), p, 2));
+  uint32x4_t pp = vaddq_u32(o->phase, vreinterpretq_u32_s32(p));
+  *bOut = vsubq_f32(vreinterpretq_f32_u32(vorrq_u32(vshrq_n_u32(pp, 9), vdupq_n_u32(0x3F800000))), vdupq_n_f32(1.0f));
+  o->phase = vdupq_n_u32(pp[3]);
+#else // HV_SIMD_NONE
+  const hv_uint32_t p = (o->phase >> 9) | 0x3F800000;
+  *bOut = *((float *) (&p)) - 1.0f;
+  o->phase += ((int) (bIn * o->step.f2sc));
+#endif
+}
+
+static inline void __hv_phasor_k_f(SignalPhasor *o, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_sub_ps(o->phase, _mm256_set1_ps(1.0f));
+  o->phase = _mm256_or_ps(_mm256_andnot_ps(
+      _mm256_set1_ps(-INFINITY),
+      _mm256_add_ps(o->phase, o->inc)),
+      _mm256_set1_ps(1.0f));
+#elif HV_SIMD_SSE
+  *bOut = _mm_sub_ps(_mm_castsi128_ps(
+      _mm_or_si128(_mm_srli_epi32(o->phase, 9),
+      (__m128i) {0x3F8000003F800000L, 0x3F8000003F800000L})),
+      _mm_set1_ps(1.0f));
+  o->phase = _mm_add_epi32(o->phase, o->inc);
+#elif HV_SIMD_NEON
+  *bOut = vsubq_f32(vreinterpretq_f32_u32(
+      vorrq_u32(vshrq_n_u32(o->phase, 9),
+      vdupq_n_u32(0x3F800000))),
+      vdupq_n_f32(1.0f));
+  o->phase = vaddq_u32(o->phase, vreinterpretq_u32_s32(o->inc));
+#else // HV_SIMD_NONE
+  const hv_uint32_t p = (o->phase >> 9) | 0x3F800000;
+  *bOut = *((float *) (&p)) - 1.0f;
+  o->phase += o->inc;
+#endif
+}
+
+#endif // _HEAVY_SIGNAL_PHASOR_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalRPole.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalRPole.h"
+
+hv_size_t sRPole_init(SignalRPole *o) {
+#if HV_SIMD_AVX
+  sDel1_init(&o->sDel1_fxiLN);
+  sDel1_init(&o->sDel1_kjkpV);
+  sDel1_init(&o->sDel1_dkIWc);
+  sDel1_init(&o->sDel1_bVeoW);
+  sDel1_init(&o->sDel1_PulZn);
+  sDel1_init(&o->sDel1_yTFig);
+  sDel1_init(&o->sDel1_Is9Qf);
+  sDel1_init(&o->sDel1_LIyNt);
+  sDel1_init(&o->sDel1_VqpU3);
+  sDel1_init(&o->sDel1_ZVYeg);
+  sDel1_init(&o->sDel1_IVAZh);
+  sDel1_init(&o->sDel1_F8WrY);
+  sDel1_init(&o->sDel1_rkFMy);
+  sDel1_init(&o->sDel1_BeqSK);
+  __hv_zero_f(&o->ym);
+#elif HV_SIMD_SSE || HV_SIMD_NEON
+  sDel1_init(&o->sDel1_i8Twk);
+  sDel1_init(&o->sDel1_KYibU);
+  sDel1_init(&o->sDel1_spa5V);
+  sDel1_init(&o->sDel1_3HXdb);
+  sDel1_init(&o->sDel1_Aj1oK);
+  sDel1_init(&o->sDel1_jNX1g);
+  __hv_zero_f(&o->ym);
+#else
+  o->ym = 0.0f;
+#endif
+  return 0;
+}
+
+void sRPole_onMessage(HvBase *_c, SignalRPole *o, int letIn, const HvMessage *m) {
+  // TODO
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalRPole.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SIGNAL_RPOLE_H_
+#define _SIGNAL_RPOLE_H_
+
+#include "HvBase.h"
+#include "SignalDel1.h"
+#include "HeavyMath.h"
+
+// implements y[n] = x[n] - a*y[n-1]
+// H(z) = 1/(1+a*z^-1)
+typedef struct SignalRPole {
+#if HV_SIMD_AVX
+  SignalDel1 sDel1_fxiLN;
+  SignalDel1 sDel1_kjkpV;
+  SignalDel1 sDel1_dkIWc;
+  SignalDel1 sDel1_bVeoW;
+  SignalDel1 sDel1_PulZn;
+  SignalDel1 sDel1_yTFig;
+  SignalDel1 sDel1_Is9Qf;
+  SignalDel1 sDel1_LIyNt;
+  SignalDel1 sDel1_VqpU3;
+  SignalDel1 sDel1_ZVYeg;
+  SignalDel1 sDel1_IVAZh;
+  SignalDel1 sDel1_F8WrY;
+  SignalDel1 sDel1_rkFMy;
+  SignalDel1 sDel1_BeqSK;
+  hv_bufferf_t ym;
+#elif HV_SIMD_SSE || HV_SIMD_NEON
+  SignalDel1 sDel1_i8Twk;
+  SignalDel1 sDel1_KYibU;
+  SignalDel1 sDel1_spa5V;
+  SignalDel1 sDel1_3HXdb;
+  SignalDel1 sDel1_Aj1oK;
+  SignalDel1 sDel1_jNX1g;
+  hv_bufferf_t ym;
+#else
+  hv_bufferf_t ym;
+#endif
+} SignalRPole;
+
+hv_size_t sRPole_init(SignalRPole *o);
+
+void sRPole_onMessage(HvBase *_c, SignalRPole *o, int letIn, const HvMessage *m);
+
+static inline void __hv_rpole_f(SignalRPole *o, hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  hv_bufferf_t a, b, c, d, e, f, g, i, j, k, l, m, n;
+  __hv_del1_f(&o->sDel1_fxiLN, bIn1, &a);
+  __hv_mul_f(bIn1, a, &b);
+  __hv_del1_f(&o->sDel1_kjkpV, a, &a);
+  __hv_mul_f(b, a, &c);
+  __hv_del1_f(&o->sDel1_dkIWc, a, &a);
+  __hv_mul_f(c, a, &d);
+  __hv_del1_f(&o->sDel1_bVeoW, a, &a);
+  __hv_mul_f(d, a, &e);
+  __hv_del1_f(&o->sDel1_PulZn, a, &a);
+  __hv_mul_f(e, a, &f);
+  __hv_del1_f(&o->sDel1_yTFig, a, &a);
+  __hv_mul_f(f, a, &g);
+  __hv_del1_f(&o->sDel1_Is9Qf, a, &a);
+  __hv_mul_f(g, a, &a);
+  __hv_del1_f(&o->sDel1_LIyNt, bIn0, &i);
+  __hv_del1_f(&o->sDel1_VqpU3, i, &j);
+  __hv_del1_f(&o->sDel1_ZVYeg, j, &k);
+  __hv_del1_f(&o->sDel1_IVAZh, k, &l);
+  __hv_del1_f(&o->sDel1_F8WrY, l, &m);
+  __hv_del1_f(&o->sDel1_rkFMy, m, &n);
+  __hv_mul_f(i, bIn1, &i);
+  __hv_sub_f(bIn0, i, &i);
+  __hv_fma_f(j, b, i, &i);
+  __hv_mul_f(k, c, &c);
+  __hv_sub_f(i, c, &c);
+  __hv_fma_f(l, d, c, &c);
+  __hv_mul_f(m, e, &e);
+  __hv_sub_f(c, e, &e);
+  __hv_fma_f(n, f, e, &e);
+  __hv_del1_f(&o->sDel1_BeqSK, n, &n);
+  __hv_mul_f(n, g, &g);
+  __hv_sub_f(e, g, &g);
+  __hv_fma_f(a, o->ym, g, &g);
+  o->ym = g;
+  *bOut = g;
+#elif HV_SIMD_SSE || HV_SIMD_NEON
+  hv_bufferf_t a, b, c, e, f;
+  __hv_del1_f(&o->sDel1_i8Twk, bIn1, &a);
+  __hv_mul_f(bIn1, a, &b);
+  __hv_del1_f(&o->sDel1_KYibU, a, &a);
+  __hv_mul_f(b, a, &c);
+  __hv_del1_f(&o->sDel1_spa5V, a, &a);
+  __hv_mul_f(c, a, &a);
+  __hv_del1_f(&o->sDel1_3HXdb, bIn0, &e);
+  __hv_del1_f(&o->sDel1_Aj1oK, e, &f);
+  __hv_mul_f(e, bIn1, &e);
+  __hv_sub_f(bIn0, e, &e);
+  __hv_fma_f(f, b, e, &e);
+  __hv_del1_f(&o->sDel1_jNX1g, f, &f);
+  __hv_mul_f(f, c, &c);
+  __hv_sub_f(e, c, &c);
+  __hv_fma_f(a, o->ym, c, &c);
+  o->ym = c;
+  *bOut = c;
+#else
+  *bOut = bIn0 - bIn1 * o->ym;
+  o->ym = *bOut;
+#endif
+}
+
+#endif // _SIGNAL_RPOLE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalSamphold.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalSamphold.h"
+
+hv_size_t sSamphold_init(SignalSamphold *o) {
+#if HV_SIMD_AVX
+  o->s = _mm256_setzero_ps();
+#elif HV_SIMD_SSE
+  o->s = _mm_setzero_ps();
+#elif HV_SIMD_NEON
+  o->s = vdupq_n_f32(0.0f);
+#else
+  o->s = 0.0f;
+#endif
+  return 0;
+}
+
+void sSamphold_onMessage(HvBase *_c, SignalSamphold *o, int letIndex,
+    const HvMessage *const m, void *sendMessage) {
+  switch (letIndex) {
+    case 2: {
+      if (msg_isFloat(m,0)) {
+#if HV_SIMD_AVX
+        o->s = _mm256_set1_ps(msg_getFloat(m,0));
+#elif HV_SIMD_SSE
+        o->s = _mm_set1_ps(msg_getFloat(m,0));
+#elif HV_SIMD_NEON
+        o->s = vdupq_n_f32(msg_getFloat(m,0));
+#else
+        o->s = msg_getFloat(m,0);
+#endif
+      }
+      break;
+    }
+    default: break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalSamphold.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,248 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SIGNAL_SAMPHOLD_H_
+#define _SIGNAL_SAMPHOLD_H_
+
+#include "HvBase.h"
+
+typedef struct SignalSamphold {
+  hv_bufferf_t s;
+} SignalSamphold;
+
+hv_size_t sSamphold_init(SignalSamphold *o);
+
+static inline void __hv_samphold_f(SignalSamphold *o, hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_samphold_f() not implemented
+#elif HV_SIMD_SSE
+  switch (_mm_movemask_ps(bIn1)) {
+    default:
+    case 0x0: *bOut = o->s; break;
+    case 0x1: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(0,0,0,0));
+      o->s = *bOut;
+      break;
+    }
+    case 0x2: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(1,1,1,1));
+      *bOut = _mm_blend_ps(o->s, x, 0xE);
+      o->s = x;
+      break;
+    }
+    case 0x3: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(1,1,1,1));
+      *bOut = _mm_blend_ps(bIn0, x, 0xC);
+      o->s = x;
+      break;
+    }
+    case 0x4: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2));
+      *bOut = _mm_blend_ps(o->s, x, 0xC);
+      o->s = x;
+      break;
+    }
+    case 0x5: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,0,0));
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2));
+      break;
+    }
+    case 0x6: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,1,0));
+      *bOut = _mm_blend_ps(o->s, x, 0xE);
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2));
+      break;
+    }
+    case 0x7: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2));
+      *bOut = _mm_blend_ps(bIn0, x, 0x8);
+      o->s = x;
+      break;
+    }
+    case 0x8: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      *bOut = _mm_blend_ps(o->s, x, 0x8);
+      o->s = x;
+      break;
+    }
+    case 0x9: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,0,0,0));
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xA: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,1,1,0));
+      *bOut = _mm_blend_ps(o->s, x, 0xE);
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xB: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,1,1,0));
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xC: {
+      *bOut = _mm_blend_ps(o->s, bIn0, 0xC);
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xD: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,2,0,0));
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xE: {
+      *bOut = _mm_blend_ps(o->s, bIn0, 0xE);
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xF: {
+      *bOut = bIn0;
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+  }
+#elif HV_SIMD_NEON
+  uint32x4_t mmA = vandq_u32(
+      vreinterpretq_u32_f32(bIn1), (uint32x4_t) {0x1, 0x2, 0x4, 0x8}); // [0 1 2 3]
+  uint32x4_t mmB = vextq_u32(mmA, mmA, 2);                             // [2 3 0 1]
+  uint32x4_t mmC = vorrq_u32(mmA, mmB);                                // [0+2 1+3 0+2 1+3]
+  uint32x4_t mmD = vextq_u32(mmC, mmC, 3);                             // [1+3 0+2 1+3 0+2]
+  uint32x4_t mmE = vorrq_u32(mmC, mmD);                                // [0+1+2+3 ...]
+  uint32_t movemask = vgetq_lane_u32(mmE, 0);
+  switch (movemask) {
+    default:
+    case 0x0: *bOut = o->s; break;
+    case 0x1: {
+      *bOut = vdupq_n_f32(vgetq_lane_f32(bIn0,0));
+      o->s = *bOut;
+      break;
+    }
+    case 0x2: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1));
+      *bOut = vextq_f32(o->s, x, 3);
+      o->s = x;
+      break;
+    }
+    case 0x3: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {~0x0, 0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, ~0x0, ~0x0, ~0x0})));
+      o->s = x;
+      break;
+    }
+    case 0x4: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,2));
+      *bOut = vextq_f32(o->s, x, 2);
+      o->s = x;
+      break;
+    }
+    case 0x5: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0));
+      const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,2));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {~0x0, ~0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, ~0x0, ~0x0})));
+      o->s = y;
+    }
+    case 0x6: {
+      const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      float32x4_t z = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {~0x0, 0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, ~0x0, ~0x0, 0x0})));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(z), (uint32x4_t) {~0x0, ~0x0, ~0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, 0x0, ~0x0})));
+      o->s = y;
+    }
+    case 0x7: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,2));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {~0x0, ~0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0x0, ~0x0, ~0x0})));
+      o->s = x;
+      break;
+    }
+    case 0x8: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      *bOut = vextq_f32(o->s, x, 1);
+      o->s = x;
+      break;
+    }
+    case 0x9: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {~0x0, ~0x0, ~0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, 0x0, 0x0, ~0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+    }
+    case 0xA: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1));
+      const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      float32x4_t z = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {~0x0, 0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, ~0x0, ~0x0, 0x0})));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(z), (uint32x4_t) {~0x0, ~0x0, ~0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, 0x0, ~0x0})));
+      o->s = y;
+    }
+    case 0xB: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {~0x0, ~0x0, 0x0, ~0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0x0, ~0x0, 0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      break;
+    }
+    case 0xC: {
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {~0x0, ~0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, 0x0, ~0x0, ~0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      break;
+    }
+    case 0xD: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {~0x0, 0x0, ~0x0, ~0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, ~0x0, 0x0, 0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+    }
+    case 0xE: {
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {~0x0, 0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, ~0x0, ~0x0, ~0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      break;
+    }
+    case 0xF: {
+      *bOut = bIn0;
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      break;
+    }
+  }
+#else // HV_SIMD_NONE
+  if (bIn1 != 0.0f) o->s = bIn0;
+  *bOut = o->s;
+#endif
+}
+
+void sSamphold_onMessage(HvBase *_c, SignalSamphold *o, int letIndex,
+    const HvMessage *const m, void *sendMessage);
+
+#endif // _SIGNAL_SAMPHOLD_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalVar.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalVar.h"
+
+// __var~f
+
+static void sVarf_update(SignalVarf *o, float k, float step, bool reverse) {
+#if HV_SIMD_AVX
+  if (reverse) o->v = _mm256_setr_ps(k+7.0f*step, k+6.0f*step, k+5.0f*step, k+4.0f*step, k+3.0f*step, k+2.0f*step, k+step, k);
+  else o->v = _mm256_set_ps(k+7.0f*step, k+6.0f*step, k+5.0f*step, k+4.0f*step, k+3.0f*step, k+2.0f*step, k+step, k);
+#elif HV_SIMD_SSE
+  if (reverse) o->v = _mm_setr_ps(k+3.0f*step, k+2.0f*step, k+step, k);
+  else o->v = _mm_set_ps(k+3.0f*step, k+2.0f*step, k+step, k);
+#elif HV_SIMD_NEON
+  if (reverse) o->v = (float32x4_t) {3.0f*step+k, 2.0f*step+k, step+k, k};
+  else o->v = (float32x4_t) {k, step+k, 2.0f*step+k, 3.0f*step+k};
+#else // HV_SIMD_NONE
+  o->v = k;
+#endif
+}
+
+hv_size_t sVarf_init(SignalVarf *o, float k, float step, bool reverse) {
+  sVarf_update(o, k, step, reverse);
+  return 0;
+}
+
+void sVarf_onMessage(HvBase *_c, SignalVarf *o, const HvMessage *m) {
+  if (msg_isFloat(m,0)) {
+    sVarf_update(o, msg_getFloat(m,0), msg_isFloat(m,1) ? msg_getFloat(m,1) : 0.0f, msg_getNumElements(m) == 3);
+  }
+}
+
+
+
+// __var~i
+
+static void sVari_update(SignalVari *o, int k, int step, bool reverse) {
+#if HV_SIMD_AVX
+  if (reverse) o->v = _mm256_setr_epi32(k+7*step, k+6*step, k+5*step, k+4*step, k+3*step, k+2*step, k+step, k);
+  else o->v = _mm256_set_epi32(k+7*step, k+6*step, k+5*step, k+4*step, k+3*step, k+2*step, k+step, k);
+#elif HV_SIMD_SSE
+  if (reverse) o->v = _mm_setr_epi32(k+3*step, k+2*step, k+step, k);
+  else o->v = _mm_set_epi32(k+3*step, k+2*step, k+step, k);
+#elif HV_SIMD_NEON
+  if (reverse) o->v = (int32x4_t) {3*step+k, 2*step+k, step+k, k};
+  else o->v = (int32x4_t) {k, step+k, 2*step+k, 3*step+k};
+#else // HV_SIMD_NEON
+  o->v = k;
+#endif
+}
+
+hv_size_t sVari_init(SignalVari *o, int k, int step, bool reverse) {
+  sVari_update(o, k, step, reverse);
+  return 0;
+}
+
+void sVari_onMessage(HvBase *_c, SignalVari *o, const HvMessage *m) {
+  if (msg_isFloat(m,0)) {
+    sVari_update(o, (int) msg_getFloat(m,0), msg_isFloat(m,1) ? (int) msg_getFloat(m,1) : 0, msg_getNumElements(m) == 3);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/SignalVar.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_SIGNAL_VAR_H_
+#define _HEAVY_SIGNAL_VAR_H_
+
+#include "HvBase.h"
+
+// __var~f
+// __varset~f
+
+typedef struct SignalVarf {
+  hv_bufferf_t v;
+} SignalVarf;
+
+hv_size_t sVarf_init(SignalVarf *o, float k, float step, bool reverse);
+
+static inline void __hv_var_f(SignalVarf *o, hv_bOutf_t bOut) {
+  *bOut = o->v;
+}
+
+static inline void sVarsetf_process(SignalVarf *o, hv_bInf_t bIn) {
+  o->v = bIn;
+}
+
+void sVarf_onMessage(HvBase *_c, SignalVarf *o, const HvMessage *m);
+
+
+
+// __var~i
+// __varset~i
+
+typedef struct SignalVari {
+  hv_bufferi_t v;
+} SignalVari;
+
+hv_size_t sVari_init(SignalVari *o, int k, int step, bool reverse);
+
+static inline void __hv_var_i(SignalVari *o, hv_bOuti_t bOut) {
+  *bOut = o->v;
+}
+
+#if HV_SIMD_AVX
+#define __hv_var_k_i_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m256i)(__v8si) {_a,_b,_c,_d,_e,_f,_g,_h})
+#define __hv_var_k_i_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m256i)(__v8si) {_h,_g,_f,_e,_d,_c,_b,_a})
+#define __hv_var_k_f_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m256) {_a,_b,_c,_d,_e,_f,_g,_h})
+#define __hv_var_k_f_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m256) {_h,_g,_f,_e,_d,_c,_b,_a})
+#elif HV_SIMD_SSE
+#define __hv_var_k_i_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m128i)(__v4si) {_a,_b,_c,_d})
+#define __hv_var_k_i_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m128i)(__v4si) {_d,_c,_b,_a})
+#define __hv_var_k_f_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m128) {_a,_b,_c,_d})
+#define __hv_var_k_f_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m128) {_d,_c,_b,_a})
+#elif HV_SIMD_NEON
+#define __hv_var_k_i_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((int32x4_t) {_a,_b,_c,_d})
+#define __hv_var_k_i_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((int32x4_t) {_d,_c,_b,_a})
+#define __hv_var_k_f_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((float32x4_t) {_a,_b,_c,_d})
+#define __hv_var_k_f_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((float32x4_t) {_d,_c,_b,_a})
+#else // HV_SIMD_NONE
+#define __hv_var_k_i_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a
+#define __hv_var_k_i_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a
+#define __hv_var_k_f_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a
+#define __hv_var_k_f_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a
+#endif
+// r == 0: forwards, r == 1: backwards
+#define __hv_var_k_i(_z,_a,_b,_c,_d,_e,_f,_g,_h,_r) __hv_var_k_i_##_r(_z,_a,_b,_c,_d,_e,_f,_g,_h)
+#define __hv_var_k_f(_z,_a,_b,_c,_d,_e,_f,_g,_h,_r) __hv_var_k_f_##_r(_z,_a,_b,_c,_d,_e,_f,_g,_h)
+
+static inline void sVarseti_process(SignalVari *o, hv_bIni_t bIn) {
+  o->v = bIn;
+}
+
+void sVari_onMessage(HvBase *_c, SignalVari *o, const HvMessage *m);
+
+#endif // _HEAVY_SIGNAL_VAR_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Utils.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,177 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_UTILS_H_
+#define _HEAVY_UTILS_H_
+
+// Type definitions
+#if _WIN32 || _WIN64 || WINAPI_FAMILY
+#define HV_WIN 1
+#include <stddef.h>
+#if defined (_MSC_VER)
+#define HV_MSVC 1
+#endif
+#define hv_size_t unsigned long
+#define hv_uint32_t unsigned int
+#define hv_uint16_t unsigned short
+#define hv_int32_t int
+#elif __APPLE__ && __MACH__
+#define HV_APPLE 1
+#include <stddef.h>
+#define hv_size_t size_t
+#define hv_uint32_t unsigned int
+#define hv_uint16_t unsigned short
+#define hv_int32_t int
+#elif __unix__ || __unix
+#define HV_UNIX 1
+#include <stddef.h>
+#include <stdint.h>
+#define hv_size_t size_t
+#define hv_uint32_t uint32_t
+#define hv_uint16_t uint16_t
+#define hv_int32_t int32_t
+#else
+#error Unsupported platform
+#endif
+
+// Memory management
+extern void *hv_alloca(hv_size_t numbytes);
+extern void *hv_malloc(hv_size_t numbytes); // allocates memory on 16 byte boundaries and clears it to zero
+extern void hv_free(void *ptr); // frees aligned memory
+extern void *hv_realloc(void *ptr, hv_size_t numBytes);
+extern void *hv_memcpy(void *dest, const void *src, hv_size_t numbytes);
+extern void *hv_memset(void *ptr, hv_size_t numbytes); // sets everything to 0
+
+// String handling
+extern hv_size_t hv_strlen(const char *str);
+extern char *hv_strncat(char *dest, const char *str, hv_size_t n);
+extern char *hv_strncpy(char *dest, const char *str, hv_size_t n);
+extern int hv_strcmp(const char *str1, const char *str2);
+extern int hv_strncmp(const char *str1, const char *str2, hv_size_t n);
+extern int hv_snprintf(char *dest, hv_size_t n, const char *format, ...);
+
+// Math
+extern int hv_max_i(int x, int y);
+extern hv_size_t hv_max_ui(hv_size_t x, hv_size_t y);
+extern int hv_min_i(int x, int y);
+extern hv_size_t hv_min_ui(hv_size_t x, hv_size_t y);
+extern float hv_max_f(float x, float y);
+extern float hv_min_f(float x, float y);
+extern double hv_max_d(double x, double y);
+extern double hv_min_d(double x, double y);
+extern float hv_sin_f(float x);
+extern float hv_sinh_f(float x);
+extern float hv_cos_f(float x);
+extern float hv_cosh_f(float x);
+extern float hv_tan_f(float x);
+extern float hv_tanh_f(float x);
+extern float hv_asin_f(float x);
+extern float hv_asinh_f(float x);
+extern float hv_acos_f(float x);
+extern float hv_acosh_f(float x);
+extern float hv_atan_f(float x);
+extern float hv_atanh_f(float x);
+extern float hv_atan2_f(float x, float y);
+extern float hv_exp_f(float x);
+extern float hv_abs_f(float x);
+extern float hv_sqrt_f(float x);
+extern float hv_log_f(float x);
+extern float hv_log2_f(float x);
+extern float hv_log10_f(float x);
+extern float hv_ceil_f(float x);
+extern float hv_floor_f(float x);
+extern float hv_round_f(float x);
+extern float hv_pow_f(float x, float y);
+extern float hv_fma_f(float x, float y, float z);
+
+// Utilities
+extern void hv_assert(int e);
+extern void hv_clear_buffer(float *b, int n);
+extern hv_uint32_t hv_min_max_log2(hv_uint32_t x);
+
+// SIMD
+#ifndef HV_SIMD_NONE
+  #define HV_SIMD_NEON __ARM_NEON__
+  #define HV_SIMD_SSE (__SSE__ && __SSE2__ && __SSE3__ && __SSSE3__ && __SSE4_1__)
+  #define HV_SIMD_AVX (__AVX__ && HV_SIMD_SSE) // it is required that if AVX exists then SSE will also be available
+  #define HV_SIMD_FMA __FMA__
+#endif
+
+#ifdef HV_WIN
+#include "Utils_windows.h"
+#elif HV_APPLE
+#include "Utils_mac.h"
+#elif HV_UNIX
+#include "Utils_unix.h"
+#else
+#error Unsupported platform
+#endif
+
+#if HV_SIMD_NEON // NEON
+  #define HV_N_SIMD 4
+  #define hv_bufferf_t float32x4_t
+  #define hv_bufferi_t int32x4_t
+  #define hv_bInf_t float32x4_t
+  #define hv_bOutf_t float32x4_t*
+  #define hv_bIni_t int32x4_t
+  #define hv_bOuti_t int32x4_t*
+  #define VIf(_x) (_x)
+  #define VOf(_x) (&_x)
+  #define VIi(_x) (_x)
+  #define VOi(_x) (&_x)
+#elif HV_SIMD_AVX // AVX
+  #define HV_N_SIMD 8
+  #define hv_bufferf_t __m256
+  #define hv_bufferi_t __m256i
+  #define hv_bInf_t __m256
+  #define hv_bOutf_t __m256*
+  #define hv_bIni_t __m256i
+  #define hv_bOuti_t __m256i*
+  #define VIf(_x) (_x)
+  #define VOf(_x) (&_x)
+  #define VIi(_x) (_x)
+  #define VOi(_x) (&_x)
+#elif HV_SIMD_SSE // SSE
+  #define HV_N_SIMD 4
+  #define hv_bufferf_t __m128
+  #define hv_bufferi_t __m128i
+  #define hv_bInf_t __m128
+  #define hv_bOutf_t __m128*
+  #define hv_bIni_t __m128i
+  #define hv_bOuti_t __m128i*
+  #define VIf(_x) (_x)
+  #define VOf(_x) (&_x)
+  #define VIi(_x) (_x)
+  #define VOi(_x) (&_x)
+#else // DEFAULT
+  #define HV_N_SIMD 1
+  #undef HV_SIMD_NONE
+  #define HV_SIMD_NONE 1
+  #define hv_bufferf_t float
+  #define hv_bufferi_t int
+  #define hv_bInf_t float
+  #define hv_bOutf_t float*
+  #define hv_bIni_t int
+  #define hv_bOuti_t int*
+  #define VIf(_x) (_x)
+  #define VOf(_x) (&_x)
+  #define VIi(_x) (_x)
+  #define VOi(_x) (&_x)
+#endif
+
+#define HV_N_SIMD_MASK (HV_N_SIMD-1)
+
+#endif // _HEAVY_UTILS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Utils_mac.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "Utils_mac.h"
+
+#if HV_APPLE
+
+hv_size_t hv_max_ui(hv_size_t x, hv_size_t y) {
+  return (x >= y) ? x : y;
+}
+
+hv_size_t hv_min_ui(hv_size_t x, hv_size_t y) {
+  return (x <= y) ? x : y;
+}
+
+int hv_max_i(int x, int y) {
+  return (x >= y) ? x : y;
+}
+
+int hv_min_i(int x, int y) {
+  return (x <= y) ? x : y;
+}
+
+hv_uint32_t hv_min_max_log2(hv_uint32_t x) {
+  // finds ceil(log2(x))
+  // http://stackoverflow.com/questions/2589096/find-most-significant-bit-left-most-that-is-set-in-a-bit-array
+  return (hv_uint32_t) ((8 * sizeof(unsigned int)) - __builtin_clz(x - 1));
+}
+
+#endif // HV_APPLE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Utils_mac.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_UTILS_MAC_H_
+#define _HEAVY_UTILS_MAC_H_
+
+#include "Utils.h"
+
+#if HV_APPLE
+#include <alloca.h>
+#if HV_SIMD_AVX || HV_SIMD_SSE
+#include <immintrin.h>
+#include <mm_malloc.h>
+#elif HV_SIMD_NEON
+#include <arm_neon.h>
+#endif
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define HV_EXPORT
+#define HV_FORCE_INLINE inline __attribute__((always_inline))
+
+// Memory management
+#define hv_alloca(_n) alloca(_n)
+#if HV_SIMD_AVX || HV_SIMD_SSE
+  #define hv_malloc(_n) _mm_malloc(_n, 32) // 32 to ensure AVX compatability (16 otherwise)
+  #define hv_free(x) _mm_free(x)
+#else
+  #define hv_malloc(_n) malloc(_n)
+  #define hv_free(x) free(x)
+#endif
+#define hv_realloc(a, b) realloc(a, b)
+#define hv_memcpy(a, b, c) memcpy(a, b, c)
+#define hv_memset(a, b) memset(a, 0, b)
+
+// Strings
+#define hv_strlen(a) strlen(a)
+#define hv_strncat(a, b, c) strncat(a, b, c)
+#define hv_strncpy(a, b, c) strncpy(a, b, c)
+#define hv_strcmp(a, b) strcmp(a, b)
+#define hv_strncmp(a, b, c) strncmp(a, b, c)
+#define hv_snprintf(a, b, c, ...) snprintf(a, b, c, __VA_ARGS__)
+
+// Math
+#define hv_max_f(a, b) fmaxf(a, b)
+#define hv_min_f(a, b) fminf(a, b)
+#define hv_max_d(a, b) fmax(a, b)
+#define hv_min_d(a, b) fmin(a, b)
+#define hv_sin_f(a) sinf(a)
+#define hv_sinh_f(a) sinhf(a)
+#define hv_cos_f(a) cosf(a)
+#define hv_cosh_f(a) coshf(a)
+#define hv_tan_f(a) tanf(a)
+#define hv_tanh_f(a) tanhf(a)
+#define hv_asin_f(a) asinf(a)
+#define hv_asinh_f(a) asinhf(a)
+#define hv_acos_f(a) acosf(a)
+#define hv_acosh_f(a) acoshf(a)
+#define hv_atan_f(a) atanf(a)
+#define hv_atanh_f(a) atanhf(a)
+#define hv_atan2_f(a, b) atan2f(a, b)
+#define hv_exp_f(a) expf(a)
+#define hv_abs_f(a) fabsf(a)
+#define hv_sqrt_f(a) sqrtf(a)
+#define hv_log_f(a) logf(a)
+#define hv_log2_f(a) log2f(a)
+#define hv_log10_f(a) log10f(a)
+#define hv_ceil_f(a) ceilf(a)
+#define hv_floor_f(a) floorf(a)
+#define hv_round_f(a) roundf(a)
+#define hv_pow_f(a, b) powf(a, b)
+#define hv_fma_f(a, b, c) ((a*b)+c) // TODO(joe): use 'fmaf(a, b, c)' once emscripten supports it
+
+// Utilities
+#define hv_assert(e) assert(e)
+#define hv_clear_buffer(b, n) memset(b, 0, (n)*sizeof(float))
+
+#endif // HV_APPLE
+#endif // _HEAVY_UTILS_MAC_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Utils_unix.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "Utils_unix.h"
+
+#if HV_UNIX
+
+hv_size_t hv_max_ui(hv_size_t x, hv_size_t y) {
+  return (x >= y) ? x : y;
+}
+
+hv_size_t hv_min_ui(hv_size_t x, hv_size_t y) {
+  return (x <= y) ? x : y;
+}
+
+int hv_max_i(int x, int y) {
+  return (x >= y) ? x : y;
+}
+
+int hv_min_i(int x, int y) {
+  return (x <= y) ? x : y;
+}
+
+hv_uint32_t hv_min_max_log2(hv_uint32_t x) {
+  // finds ceil(log2(x))
+  // http://stackoverflow.com/questions/2589096/find-most-significant-bit-left-most-that-is-set-in-a-bit-array
+  return (hv_uint32_t) ((8 * sizeof(unsigned int)) - __builtin_clz(x - 1));
+}
+
+#endif // HV_UNIX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Utils_unix.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_UTILS_UNIX_H_
+#define _HEAVY_UTILS_UNIX_H_
+
+#include "Utils.h"
+
+#if HV_UNIX
+#if HV_SIMD_AVX || HV_SIMD_SSE
+#include <immintrin.h>
+#include <mm_malloc.h>
+#elif HV_SIMD_NEON
+#include <arm_neon.h>
+#endif
+#include <alloca.h>
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define HV_EXPORT
+#define HV_FORCE_INLINE inline __attribute__((always_inline))
+
+// Memory management
+#define hv_alloca(_n) alloca(_n)
+#if HV_SIMD_AVX || HV_SIMD_SSE
+  #define hv_malloc(_n) _mm_malloc(_n, 32) // 32 to ensure AVX compatability (16 otherwise)
+  #define hv_free(x) _mm_free(x)
+#else
+  #define hv_malloc(_n) malloc(_n)
+  #define hv_free(_n) free(_n)
+#endif
+#define hv_realloc(a, b) realloc(a, b)
+#define hv_memcpy(a, b, c) memcpy(a, b, c)
+#define hv_memset(a, b) memset(a, 0, b)
+
+// Strings
+#define hv_strlen(a) strlen(a)
+#define hv_strncat(a, b, c) strncat(a, b, c)
+#define hv_strncpy(a, b, c) strncpy(a, b, c)
+#define hv_strcmp(a, b) strcmp(a, b)
+#define hv_strncmp(a, b, c) strncmp(a, b, c)
+#define hv_snprintf(a, b, c, ...) snprintf(a, b, c, __VA_ARGS__)
+
+// Math
+#define hv_max_f(a, b) fmaxf(a, b)
+#define hv_min_f(a, b) fminf(a, b)
+#define hv_max_d(a, b) fmax(a, b)
+#define hv_min_d(a, b) fmin(a, b)
+#define hv_sin_f(a) sinf(a)
+#define hv_sinh_f(a) sinhf(a)
+#define hv_cos_f(a) cosf(a)
+#define hv_cosh_f(a) coshf(a)
+#define hv_tan_f(a) tanf(a)
+#define hv_tanh_f(a) tanhf(a)
+#define hv_asin_f(a) asinf(a)
+#define hv_asinh_f(a) asinhf(a)
+#define hv_acos_f(a) acosf(a)
+#define hv_acosh_f(a) acoshf(a)
+#define hv_atan_f(a) atanf(a)
+#define hv_atanh_f(a) atanhf(a)
+#define hv_atan2_f(a, b) atan2f(a, b)
+#define hv_exp_f(a) expf(a)
+#define hv_abs_f(a) fabsf(a)
+#define hv_sqrt_f(a) sqrtf(a)
+#define hv_log_f(a) logf(a)
+#define hv_log2_f(a) log2f(a)
+#define hv_log10_f(a) log10f(a)
+#define hv_ceil_f(a) ceilf(a)
+#define hv_floor_f(a) floorf(a)
+#define hv_round_f(a) roundf(a)
+#define hv_pow_f(a, b) powf(a, b)
+#define hv_fma_f(a, b, c) ((a*b)+c) // TODO(joe): use 'fmaf(a, b, c)' once emscripten supports it
+
+// Utilities
+#define hv_assert(e) assert(e)
+#define hv_clear_buffer(b, n) memset(b, 0, n*sizeof(float))
+
+#endif // HV_UNIX
+#endif // _HEAVY_UTILS_UNIX_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Utils_windows.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "Utils_windows.h"
+
+#if HV_WIN
+
+hv_size_t hv_max_ui(hv_size_t x, hv_size_t y) {
+  return (x >= y) ? x : y;
+}
+
+hv_size_t hv_min_ui(hv_size_t x, hv_size_t y) {
+  return (x <= y) ? x : y;
+}
+
+int hv_max_i(int x, int y) {
+  return (x >= y) ? x : y;
+}
+
+int hv_min_i(int x, int y) {
+  return (x <= y) ? x : y;
+}
+
+hv_uint32_t hv_min_max_log2(hv_uint32_t x) {
+#if HV_MSVC
+  // finds ceil(log2(x))
+  // http://stackoverflow.com/questions/2589096/find-most-significant-bit-left-most-that-is-set-in-a-bit-array
+  // http://msdn.microsoft.com/en-us/library/fbxyd7zd%28v=VS.80%29.aspx
+  unsigned long z = 0;
+  _BitScanReverse(&z, x);
+  return (hv_uint32_t) (z+1);
+#else
+  return (hv_uint32_t) ((8 * sizeof(unsigned int)) - __builtin_clz(x-1));
+#endif // HV_MSVC
+}
+
+#if HV_MSVC
+int hv_snprintf(char* str, hv_size_t size, const char* format, ...) {
+  // http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+	int count = -1;
+	va_list ap;
+	va_start(ap, format);
+
+	if (size != 0) {
+		count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
+	}
+	if (count == -1) {
+		count = _vscprintf(format, ap);
+	}
+	va_end(ap);
+	return count;
+}
+#endif // HV_MSVC
+#endif // HV_WIN
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/Utils_windows.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_UTILS_WINDOWS_H_
+#define _HEAVY_UTILS_WINDOWS_H_
+
+#include "Utils.h"
+
+#if HV_WIN
+#define _USE_MATH_DEFINES
+#if HV_SIMD_AVX || HV_SIMD_SSE
+#if HV_MSVC
+#include <intrin.h>
+#else
+#include <immintrin.h>
+#endif
+#elif HV_SIMD_NEON
+#include <arm_neon.h>
+#endif
+#include <malloc.h>
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define HV_EXPORT __declspec(dllexport)
+
+// MSVC Specific
+#if HV_MSVC
+#define inline __inline
+#define HV_FORCE_INLINE __forceinline
+#else
+#define HV_FORCE_INLINE inline __attribute__((always_inline))
+#define hv_snprintf(a, b, c, ...) snprintf(a, b, c, __VA_ARGS__)
+#endif // HV_MSVC
+
+// Memory management
+#define hv_alloca(_n) _alloca(_n)
+#if !defined(HV_SIMD_AVX) || !defined(HV_SIMD_SSE)
+#define hv_malloc(_n) _aligned_malloc(_n, 32)
+#define hv_free(x) _aligned_free(x)
+#else
+#define hv_malloc(_n) malloc(_n)
+#define hv_free(_n) free(_n)
+#endif
+#define hv_realloc(a, b) realloc(a, b)
+#define hv_memcpy(a, b, c) memcpy(a, b, c)
+#define hv_memset(a, b) memset(a, 0, b)
+
+// Strings
+#define hv_strncat(a, b, c) strncat(a, b, c)
+#define hv_strcmp(a, b) strcmp(a, b)
+#define hv_strncmp(a, b, c) strncmp(a, b, c)
+#define hv_strncpy(a, b, c) strncpy(a, b, c)
+#define hv_strlen(a) strlen(a)
+
+// Math
+#define hv_max_f(a, b) fmaxf(a, b)
+#define hv_min_f(a, b) fminf(a, b)
+#define hv_max_d(a, b) fmax(a, b)
+#define hv_min_d(a, b) fmin(a, b)
+#define hv_sin_f(a) sinf(a)
+#define hv_sinh_f(a) sinhf(a)
+#define hv_cos_f(a) cosf(a)
+#define hv_cosh_f(a) coshf(a)
+#define hv_tan_f(a) tanf(a)
+#define hv_tanh_f(a) tanhf(a)
+#define hv_asin_f(a) asinf(a)
+#define hv_asinh_f(a) asinhf(a)
+#define hv_acos_f(a) acosf(a)
+#define hv_acosh_f(a) acoshf(a)
+#define hv_atan_f(a) atanf(a)
+#define hv_atanh_f(a) atanhf(a)
+#define hv_atan2_f(a, b) atan2f(a, b)
+#define hv_exp_f(a) expf(a)
+#define hv_abs_f(a) fabsf(a)
+#define hv_sqrt_f(a) sqrtf(a)
+#define hv_log_f(a) logf(a)
+#define hv_log2_f(a) log2f(a)
+#define hv_log10_f(a) log10f(a)
+#define hv_ceil_f(a) ceilf(a)
+#define hv_floor_f(a) floorf(a)
+#define hv_round_f(a) roundf(a)
+#define hv_pow_f(a, b) powf(a, b)
+#define hv_fma_f(a, b, c) ((a*b)+c) // TODO(joe): use 'fmaf(a, b, c)' once emscripten supports it
+
+// Utilities
+#define hv_assert(e) assert(e)
+#define hv_clear_buffer(b, n) memset(b, 0, n*sizeof(float))
+
+#endif // HV_WIN
+#endif // _HEAVY_UTILS_WINDOWS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/hello-world/render.cpp	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,183 @@
+/*
+ * render.cpp
+ *
+ *  Template render.cpp file for on-board heavy compiling
+ *
+ *  N.B. this is currently *not* compatible with foleyDesigner source files!
+ *
+ *  Created on: November 5, 2015
+ *
+ *  Christian Heinrichs
+ *
+ */
+
+#include <BeagleRT.h>
+#include <cmath>
+#include "../include/Utilities.h"
+#include "Heavy_bbb.h"
+
+// #include "I2c_TouchKey.h"
+
+// #include "../include/UdpServer.h"
+// #include "../include/UdpClient.h"
+// #include <iostream>
+// #include <fstream>
+// #include "../include/ReceiveAudioThread.h"
+
+// #include "../include/render.h"
+// #include <arm_neon.h>
+// #include <time.h>
+// #include <sndfile.h>
+
+// #include "../include/RTAudio.h"
+// #include <rtdk.h>
+
+
+/*
+ *	HEAVY CONTEXT & BUFFERS
+ */
+
+Hv_bbb *gHeavyContext;
+float *gHvInputBuffers = NULL, *gHvOutputBuffers = NULL;
+int gHvInputChannels = 0, gHvOutputChannels = 0;
+
+float gInverseSampleRate;
+
+/*
+ *	HEAVY FUNCTIONS
+ */
+
+void printHook(double timestampSecs, const char *printLabel, const char *msgString, void *userData) {
+  printf("Message from Heavy patch: [@ %.3f] %s: %s\n", timestampSecs, printLabel, msgString);
+}
+
+static void sendHook(
+    double timestamp, // in milliseconds
+    const char *receiverName,
+    const HvMessage *const m,
+    void *userData) {
+
+  // only react to messages sent to receivers named "hello"
+  if (!strncmp(receiverName, "hello", 5)) {
+  }
+
+}
+
+/*
+ * RENDER INITIALISATION, LOOP & CLEANUP
+ */
+
+
+// bool initialise_render(int numMatrixChannels, int numAudioChannels,
+// 					   int numMatrixFramesPerPeriod,
+// 					   int numAudioFramesPerPeriod,
+// 					   float matrixSampleRate, float audioSampleRate,
+// 					   void *userData)
+// {
+bool setup(BeagleRTContext *context, void *userData)	{
+
+	/* HEAVY */
+
+	gHeavyContext = hv_bbb_new(context->audioSampleRate);
+
+	gHvInputChannels = hv_getNumInputChannels(gHeavyContext);
+	gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext);
+
+	// srand ( time(NULL) );  	
+
+	rt_printf("Starting Heavy context with %d input channels and %d output channels\n",
+			  gHvInputChannels, gHvOutputChannels);
+
+	if(gHvInputChannels != 0) {
+		gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float));
+		//memset(gHvInputBuffers,0,gHvInputChannels * numAudioFramesPerPeriod * sizeof(float));
+	}
+	if(gHvOutputChannels != 0) {
+		gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float));
+	}
+
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+
+	// Set heavy print hook
+	hv_setPrintHook(gHeavyContext, &printHook);
+	// Set heavy send hook
+	hv_setSendHook(gHeavyContext, sendHook);
+
+	return true;
+}
+
+
+// void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
+// 			uint16_t *matrixIn, uint16_t *matrixOut)
+// {	
+void render(BeagleRTContext *context, void *userData)
+{
+	// use this for thread management
+	// if(gCount == 0) {
+	// } else {
+	// }
+	// gCount++;
+
+	// De-interleave the data
+	if(gHvInputBuffers != NULL) {
+		for(int n = 0; n < context->audioFrames; n++) {
+			for(int ch = 0; ch < gHvInputChannels; ch++) {
+				if(ch >= context->audioChannels+context->analogChannels) {
+					// THESE ARE PARAMETER INPUT 'CHANNELS' USED FOR ROUTING
+					// 'sensor' outputs from routing channels of dac~ are passed through here
+					break;
+				} else {
+					// If more than 2 ADC inputs are used in the pd patch, route the analog inputs
+					// i.e. ADC3->analogIn0 etc. (first two are always audio inputs)
+					if(ch >= context->audioChannels)	{
+						int m = n/2;
+						float mIn = context->analogIn[m*context->analogChannels + (ch-context->audioChannels)];
+						gHvInputBuffers[ch * context->audioFrames + n] = mIn;
+					} else {
+						gHvInputBuffers[ch * context->audioFrames + n] = context->audioIn[n * context->audioChannels + ch];
+					}
+				}
+			}
+		}
+	}
+
+	// replacement for bang~ object
+	//hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b");
+
+	hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames);
+
+	// Interleave the output data
+	if(gHvOutputBuffers != NULL) {
+		for(int n = 0; n < context->audioFrames; n++) {
+
+			for(int ch = 0; ch < gHvOutputChannels; ch++) {
+				if(ch >= context->audioChannels+context->analogChannels) {
+					// THESE ARE SENSOR OUTPUT 'CHANNELS' USED FOR ROUTING
+					// they are the content of the 'sensor output' dac~ channels
+				} else {
+					if(ch >= context->audioChannels)	{
+						int m = n/2;
+						// float mOut = (float)gHvOutputBuffers[ch*numAudioFrames + n];
+						// mOut = constrain(mOut,0.0,1.0);
+						context->analogOut[m * context->analogFrames + (ch-context->audioChannels)] = constrain(gHvOutputBuffers[ch*context->audioFrames + n],0.0,1.0);
+					} else {
+						context->audioOut[n * context->audioChannels + ch] = gHvOutputBuffers[ch * context->audioFrames + n];
+					}
+				}
+			}
+		}
+	}
+
+}
+
+
+void cleanup(BeagleRTContext *context, void *userData)
+{
+
+	hv_bbb_free(gHeavyContext);
+	if(gHvInputBuffers != NULL)
+		free(gHvInputBuffers);
+	if(gHvOutputBuffers != NULL)
+		free(gHvOutputBuffers);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/pd/hello-world/_main.pd	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,19 @@
+#N canvas 275 504 617 247 10;
+#X text 304 48 ├┴┐├┤-├─┤│-┬│--├┤-╠╦╝-║-
+;
+#X text 304 36 ┌┐-┌─┐┌─┐┌─┐┬--┌─┐╦═╗╔╦╗
+;
+#X text 304 57 └─┘└─┘┴-┴└─┘┴─┘└─┘╩╚═-╩-
+;
+#X text 353 76 powered by heavy;
+#X text 299 68 -------------------------;
+#X text 340 101 http://beaglert.cc;
+#X obj 55 192 dac~ 1 2;
+#X obj 55 151 *~ 0.1;
+#X obj 55 130 osc~ 440;
+#X text 51 51 Hello world!;
+#X text 51 61 ============;
+#X text 111 128 (the sweet sound of success);
+#X connect 7 0 6 1;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/pd/samphold/_main.pd	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,29 @@
+#N canvas 275 504 617 247 10;
+#X text 304 48 ├┴┐├┤-├─┤│-┬│--├┤-╠╦╝-║-
+;
+#X text 304 36 ┌┐-┌─┐┌─┐┌─┐┬--┌─┐╦═╗╔╦╗
+;
+#X text 304 57 └─┘└─┘┴-┴└─┘┴─┘└─┘╩╚═-╩-
+;
+#X text 353 76 powered by heavy;
+#X text 299 68 -------------------------;
+#X text 340 101 http://beaglert.cc;
+#X obj 55 212 dac~ 1 2;
+#X obj 55 171 *~ 0.1;
+#X obj 55 150 osc~ 440;
+#X text 111 148 (the sweet sound of success);
+#X obj 55 61 noise~;
+#X obj 55 128 samphold~;
+#X text 51 21 ==================;
+#X text 51 11 Sample and hold FM;
+#X obj 55 85 lop~ 1;
+#X obj 122 107 phasor~ 880;
+#X obj 55 107 *~ 1e+06;
+#X connect 7 0 6 1;
+#X connect 7 0 6 0;
+#X connect 8 0 7 0;
+#X connect 10 0 14 0;
+#X connect 11 0 8 0;
+#X connect 14 0 16 0;
+#X connect 15 0 11 1;
+#X connect 16 0 11 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlBinop.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,94 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlBinop.h"
+
+hv_size_t cBinop_init(ControlBinop *o, float k) {
+  o->k = k;
+  return 0;
+}
+
+static float cBinop_perform_op(BinopType op, float f, const float k) {
+  switch (op) {
+    case HV_BINOP_ADD: return f + k;
+    case HV_BINOP_SUBTRACT: return f - k;
+    case HV_BINOP_MULTIPLY: return f * k;
+    case HV_BINOP_DIVIDE: return (k != 0.0f) ? f / k : 0.0f;
+    case HV_BINOP_INT_DIV: return (float) ((int) f / (int) k);
+    case HV_BINOP_MOD_BIPOLAR: return (float) ((int) f % (int) k);
+    case HV_BINOP_MOD_UNIPOLAR: {
+      f = (k == 0.0f) ? 0.0f : (float) ((int) f % (int) k);
+      return (f < 0.0f) ? f + fabsf(k) : f;
+    }
+    case HV_BINOP_BIT_LEFTSHIFT: return (float) (((int) f) << ((int) k));
+    case HV_BINOP_BIT_RIGHTSHIFT: return (float) (((int) f) >> ((int) k));
+    case HV_BINOP_BIT_AND: return (float) ((int) f & (int) k);
+    case HV_BINOP_BIT_XOR: return (float) ((int) f ^ (int) k);
+    case HV_BINOP_BIT_OR: return (float) ((int) f | (int) k);
+    case HV_BINOP_EQ: return (f == k) ? 1.0f : 0.0f;
+    case HV_BINOP_NEQ: return (f != k) ? 1.0f : 0.0f;
+    case HV_BINOP_LOGICAL_AND: return ((f == 0.0f) || (k == 0.0f)) ? 0.0f : 1.0f;
+    case HV_BINOP_LOGICAL_OR: return ((f == 0.0f) && (k == 0.0f)) ? 0.0f : 1.0f;
+    case HV_BINOP_LESS_THAN: return (f < k) ? 1.0f : 0.0f;
+    case HV_BINOP_LESS_THAN_EQL: return (f <= k) ? 1.0f : 0.0f;
+    case HV_BINOP_GREATER_THAN: return (f > k) ? 1.0f : 0.0f;
+    case HV_BINOP_GREATER_THAN_EQL: return (f >= k) ? 1.0f : 0.0f;
+    case HV_BINOP_MAX: return hv_max_f(f, k);
+    case HV_BINOP_MIN: return hv_min_f(f, k);
+    case HV_BINOP_POW: return (f > 0.0f) ? powf(f, k) : 0.0f;
+    case HV_BINOP_ATAN2: return ((f == 0.0f) && (k == 0.0f)) ? 0.0f : atan2f(f, k);
+    default: return 0.0f;
+  }
+}
+
+void cBinop_onMessage(HvBase *_c, ControlBinop *o, BinopType op, int letIn,
+    const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+  switch (letIn) {
+    case 0: {
+      if (msg_isFloat(m, 0)) {
+        // Note(joe): supporting Pd's ability to perform operations of packs
+        // of floats is likely to not be supported in the future.
+        if (msg_isFloat(m, 1)) o->k = msg_getFloat(m, 1);
+        HvMessage *n = HV_MESSAGE_ON_STACK(1);
+        float f = cBinop_perform_op(op, msg_getFloat(m, 0), o->k);
+        msg_initWithFloat(n, msg_getTimestamp(m), f);
+        sendMessage(_c, 0, n);
+      }
+      break;
+    }
+    case 1: {
+      if (msg_isFloat(m, 0)) {
+        o->k = msg_getFloat(m, 0);
+      }
+      break;
+    }
+    default: break;
+  }
+}
+
+void cBinop_k_onMessage(HvBase *_c, void *o, BinopType op, const float k,
+    int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+  if (msg_isFloat(m, 0)) {
+    // NOTE(mhroth): Heavy does not support sending bangs to binop objects to return the previous output
+    float f = (msg_isFloat(m, 1)) ? msg_getFloat(m, 1) : k;
+    HvMessage *n = HV_MESSAGE_ON_STACK(1);
+    f = cBinop_perform_op(op, msg_getFloat(m, 0), f);
+    msg_initWithFloat(n, msg_getTimestamp(m), f);
+    sendMessage(_c, 0, n);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlBinop.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_BINOP_H_
+#define _HEAVY_CONTROL_BINOP_H_
+
+#include "HvBase.h"
+
+typedef enum BinopType {
+  HV_BINOP_ADD,
+  HV_BINOP_SUBTRACT,
+  HV_BINOP_MULTIPLY,
+  HV_BINOP_DIVIDE,
+  HV_BINOP_INT_DIV,
+  HV_BINOP_MOD_BIPOLAR,
+  HV_BINOP_MOD_UNIPOLAR,
+  HV_BINOP_BIT_LEFTSHIFT,
+  HV_BINOP_BIT_RIGHTSHIFT,
+  HV_BINOP_BIT_AND,
+  HV_BINOP_BIT_XOR,
+  HV_BINOP_BIT_OR,
+  HV_BINOP_EQ,
+  HV_BINOP_NEQ,
+  HV_BINOP_LOGICAL_AND,
+  HV_BINOP_LOGICAL_OR,
+  HV_BINOP_LESS_THAN,
+  HV_BINOP_LESS_THAN_EQL,
+  HV_BINOP_GREATER_THAN,
+  HV_BINOP_GREATER_THAN_EQL,
+  HV_BINOP_MAX,
+  HV_BINOP_MIN,
+  HV_BINOP_POW,
+  HV_BINOP_ATAN2
+} BinopType;
+
+typedef struct ControlBinop {
+  float k;
+} ControlBinop;
+
+hv_size_t cBinop_init(ControlBinop *o, float k);
+
+void cBinop_onMessage(HvBase *_c, ControlBinop *o, BinopType op, int letIn,
+    const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+void cBinop_k_onMessage(HvBase *_c, void *o, BinopType op, const float k,
+    int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+#endif // _HEAVY_CONTROL_BINOP_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlRandom.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlRandom.h"
+#include "HvBase.h"
+
+// http://www.firstpr.com.au/dsp/rand31
+// http://en.wikipedia.org/wiki/Lehmer_random_number_generator
+
+hv_size_t cRandom_init(ControlRandom *o, int seed) {
+  o->state = (seed != 0) ? seed : 1;
+  return 0;
+}
+
+void cRandom_onMessage(HvBase *_c, ControlRandom *o, int inletIndex, const HvMessage *m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *)) {
+  switch (inletIndex) {
+    case 0: {
+      HvMessage *n = HV_MESSAGE_ON_STACK(1);
+      o->state = (int) ((((unsigned long long) o->state) * 279470273UL) % 4294967291UL);
+      float f = ((float) (o->state >> 9)) * 0.00000011920929f;
+      msg_initWithFloat(n, msg_getTimestamp(m), f);
+      sendMessage(_c, 0, n);
+      break;
+    }
+    case 1: {
+      if (msg_isFloat(m,0)) {
+        o->state = (int) msg_getFloat(m,0);
+      }
+      break;
+    }
+    default: break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlRandom.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_RANDOM_H_
+#define _HEAVY_CONTROL_RANDOM_H_
+
+#include "HvBase.h"
+
+typedef struct ControlRandom {
+  unsigned int state;
+} ControlRandom;
+
+hv_size_t cRandom_init(ControlRandom *o, int seed);
+
+void cRandom_onMessage(HvBase *_c, ControlRandom *o, int letIndex, const HvMessage *m,
+  void (*sendMessage)(HvBase *, int, const HvMessage *));
+
+#endif // _HEAVY_CONTROL_RANDOM_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlSystem.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlSystem.h"
+#include "HvTable.h"
+
+void cSystem_onMessage(HvBase *_c, void *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+
+  HvMessage *n = HV_MESSAGE_ON_STACK(1);
+  if (msg_compareSymbol(m, 0, "samplerate")) {
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) ctx_getSampleRate(_c));
+  } else if (msg_compareSymbol(m, 0, "numInputChannels")) {
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) ctx_getNumInputChannels(_c));
+  } else if (msg_compareSymbol(m, 0, "numOutputChannels")) {
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) ctx_getNumOutputChannels(_c));
+  } else if (msg_compareSymbol(m, 0, "currentTime")) {
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) msg_getTimestamp(m));
+  } else if (msg_compareSymbol(m, 0, "table")) {
+    // NOTE(mhroth): no need to check message format for symbols as table lookup will fail otherwise
+    HvTable *o = ctx_getTableForHash(_c, msg_getHash(m,1));
+    if (o != NULL) {
+      if (msg_compareSymbol(m, 2, "length")) {
+        msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getLength(o));
+      } else if (msg_compareSymbol(m, 2, "size")) {
+        msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getSize(o));
+      } else if (msg_compareSymbol(m, 2, "head")) {
+        msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getHead(o));
+      } else return;
+    } else return;
+  } else return;
+  sendMessage(_c, 0, n);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlSystem.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_SYSTEM_H_
+#define _HEAVY_CONTROL_SYSTEM_H_
+
+#include "HvBase.h"
+
+void cSystem_onMessage(HvBase *_c, void *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+#endif // _HEAVY_CONTROL_SYSTEM_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlUnop.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlUnop.h"
+#include "HvBase.h"
+
+void cUnop_onMessage(HvBase *_c, UnopType op, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const )) {
+  if (msg_isFloat(m, 0)) {
+    float f = msg_getFloat(m, 0);
+    switch (op) {
+      case HV_UNOP_SIN: f = hv_sin_f(f); break;
+      case HV_UNOP_SINH: f = hv_sinh_f(f); break;
+      case HV_UNOP_COS: f = hv_cos_f(f); break;
+      case HV_UNOP_COSH: f = hv_cosh_f(f); break;
+      case HV_UNOP_TAN: f = hv_tan_f(f); break;
+      case HV_UNOP_TANH: f = hv_tanh_f(f); break;
+      case HV_UNOP_ASIN: f = hv_asin_f(f); break;
+      case HV_UNOP_ASINH: f = hv_asinh_f(f); break;
+      case HV_UNOP_ACOS: f = hv_acos_f(f); break;
+      case HV_UNOP_ACOSH: f = hv_acosh_f(f); break;
+      case HV_UNOP_ATAN: f = hv_atan_f(f); break;
+      case HV_UNOP_ATANH: f = hv_atanh_f(f); break;
+      case HV_UNOP_EXP: f = hv_exp_f(f); break;
+      case HV_UNOP_ABS: f = hv_abs_f(f); break;
+      case HV_UNOP_SQRT: f = (f > 0.0f) ? hv_sqrt_f(f) : 0.0f; break;
+      case HV_UNOP_LOG: f = (f > 0.0f) ? hv_log_f(f) : 0.0f; break;
+      case HV_UNOP_LOG2: f = (f > 0.0f) ? hv_log2_f(f) : 0.0f; break;
+      case HV_UNOP_LOG10: f = (f > 0.0f) ? hv_log10_f(f) : 0.0f; break;
+      case HV_UNOP_CEIL: f = hv_ceil_f(f); break;
+      case HV_UNOP_FLOOR: f = hv_floor_f(f); break;
+      case HV_UNOP_ROUND: f = hv_round_f(f); break;
+      default: return;
+    }
+    HvMessage *n = HV_MESSAGE_ON_STACK(1);
+    msg_initWithFloat(n, m->timestamp, f);
+    sendMessage(_c, 0, n);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlUnop.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_UNOP_H_
+#define _HEAVY_CONTROL_UNOP_H_
+
+struct HvBase;
+struct HvMessage;
+
+typedef enum UnopType {
+  HV_UNOP_ASIN,
+  HV_UNOP_ASINH,
+  HV_UNOP_ACOS,
+  HV_UNOP_ACOSH,
+  HV_UNOP_ATAN,
+  HV_UNOP_ATANH,
+  HV_UNOP_SIN,
+  HV_UNOP_SINH,
+  HV_UNOP_COS,
+  HV_UNOP_COSH,
+  HV_UNOP_TAN,
+  HV_UNOP_TANH,
+  HV_UNOP_EXP,
+  HV_UNOP_ABS,
+  HV_UNOP_SQRT,
+  HV_UNOP_LOG,
+  HV_UNOP_LOG2,
+  HV_UNOP_LOG10,
+  HV_UNOP_CEIL,
+  HV_UNOP_FLOOR,
+  HV_UNOP_ROUND
+} UnopType;
+
+void cUnop_onMessage(struct HvBase *_c, UnopType op, const struct HvMessage *const m,
+    void (*sendMessage)(struct HvBase *, int, const struct HvMessage *const));
+
+#endif // _HEAVY_CONTROL_UNOP_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlVar.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ControlVar.h"
+
+hv_size_t cVar_init_f(ControlVar *o, float k) {
+  o->e.type = FLOAT;
+  o->e.data.f = k;
+  return 0;
+}
+
+hv_size_t cVar_init_s(ControlVar *o, const char *s) {
+  o->e.type = HASH;
+  o->e.data.h = msg_symbolToHash(s);
+  return 0;
+}
+
+void cVar_free(ControlVar *o) {
+  // nothing to do
+}
+
+void cVar_onMessage(HvBase *_c, ControlVar *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+  switch (letIn) {
+    case 0: {
+      switch (msg_getType(m,0)) {
+        case BANG: {
+          HvMessage *n = HV_MESSAGE_ON_STACK(1);
+          if (o->e.type == FLOAT) msg_initWithFloat(n, msg_getTimestamp(m), o->e.data.f);
+          else if (o->e.type == HASH) msg_initWithHash(n, msg_getTimestamp(m), o->e.data.h);
+          else return;
+          sendMessage(_c, 0, n);
+          break;
+        }
+        case FLOAT: {
+          o->e.type = FLOAT;
+          o->e.data.f = msg_getFloat(m,0);
+          sendMessage(_c, 0, m);
+          break;
+        }
+        case SYMBOL:
+        case HASH: {
+          o->e.type = HASH;
+          o->e.data.h = msg_getHash(m,0);
+          sendMessage(_c, 0, m);
+          break;
+        }
+        default: return;
+      }
+      break;
+    }
+    case 1: {
+      switch (msg_getType(m,0)) {
+        case FLOAT: {
+          o->e.type = FLOAT;
+          o->e.data.f = msg_getFloat(m,0);
+          break;
+        }
+        case SYMBOL:
+        case HASH: {
+          o->e.type = HASH;
+          o->e.data.h = msg_getHash(m,0);
+          break;
+        }
+        default: break;
+      }
+    }
+    default: return;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/ControlVar.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_CONTROL_VAR_H_
+#define _HEAVY_CONTROL_VAR_H_
+
+#include "HvBase.h"
+
+typedef struct ControlVar {
+  Element e; // type is only every FLOAT or HASH
+} ControlVar;
+
+hv_size_t cVar_init_f(ControlVar *o, float k);
+
+hv_size_t cVar_init_s(ControlVar *o, const char *s);
+
+void cVar_free(ControlVar *o);
+
+void cVar_onMessage(HvBase *_c, ControlVar *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+#endif // _HEAVY_CONTROL_VAR_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Heavy.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,196 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "HvBase.h"
+#include "HvTable.h"
+
+#if !HV_WIN
+#pragma mark - Heavy Table
+#endif
+
+int hv_table_resize(HvTable *o, hv_uint32_t newLength) {
+  return hTable_resize(o, newLength);
+}
+
+float *hv_table_getBuffer(HvTable *o) {
+  return hTable_getBuffer(o);
+}
+
+hv_size_t hv_table_getLength(HvTable *o) {
+  return hTable_getLength(o);
+}
+
+
+
+#if !HV_WIN
+#pragma mark - Heavy Message
+#endif
+
+hv_size_t hv_msg_getByteSize (hv_uint32_t numElements) {
+  return msg_getByteSize(numElements);
+}
+
+void hv_msg_init(HvMessage *m, int numElements, hv_uint32_t timestamp) {
+  msg_init(m, numElements, timestamp);
+}
+
+hv_size_t hv_msg_getNumElements(const HvMessage *const m) {
+  return msg_getNumElements(m);
+}
+
+double hv_msg_getTimestamp(const HvMessage *const m) {
+  return msg_getTimestamp(m);
+}
+
+void hv_msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp) {
+  msg_setTimestamp(m, timestamp);
+}
+
+bool hv_msg_isBang(const HvMessage *const m, int i) {
+  return msg_isBang(m,i);
+}
+
+void hv_msg_setBang(HvMessage *m, int i) {
+  msg_setBang(m,i);
+}
+
+bool hv_msg_isFloat(const HvMessage *const m, int i) {
+  return msg_isFloat(m, i);
+}
+
+float hv_msg_getFloat(const HvMessage *const m, int i) {
+  return msg_getFloat(m,i);
+}
+
+void hv_msg_setFloat(HvMessage *m, int i, float f) {
+  msg_setFloat(m,i,f);
+}
+
+bool hv_msg_isSymbol(const HvMessage *const m, int i) {
+  return msg_isSymbol(m,i);
+}
+
+char *hv_msg_getSymbol(const HvMessage *const m, int i) {
+  return msg_getSymbol(m,i);
+}
+
+void hv_msg_setSymbol(HvMessage *m, int i, char *s) {
+  msg_setSymbol(m,i,s);
+}
+
+bool hv_msg_isHash(const HvMessage *const m, int i) {
+  return msg_isHash(m, i);
+}
+
+unsigned int hv_msg_getHash(const HvMessage *const m, int i) {
+  return msg_getHash(m, i);
+}
+
+bool hv_msg_hasFormat(const HvMessage *const m, const char *fmt) {
+  return msg_hasFormat(m, fmt);
+}
+
+char *hv_msg_toString(const HvMessage *const m) {
+  return msg_toString(m);
+}
+
+HvMessage *hv_msg_copy(HvMessage *m) {
+  return msg_copy(m);
+}
+
+void hv_msg_free(HvMessage *m) {
+  msg_free(m);
+}
+
+
+
+#if !HV_WIN
+#pragma mark - Heavy Common
+#endif
+
+double hv_getSampleRate(HvBase *c) {
+  return ctx_getSampleRate(c);
+}
+
+int hv_getNumInputChannels(HvBase *c) {
+  return ctx_getNumInputChannels(c);
+}
+
+int hv_getNumOutputChannels(HvBase *c) {
+  return ctx_getNumOutputChannels(c);
+}
+
+const char *hv_getName(HvBase *c) {
+  return ctx_getName(c);
+}
+
+void hv_setPrintHook(HvBase *c, void (*f)(double, const char *, const char *, void *)) {
+  ctx_setPrintHook(c, f);
+}
+
+void hv_setSendHook(HvBase *c, void (*f)(double, const char *, const HvMessage *const, void *)) {
+  ctx_setSendHook(c, f);
+}
+
+void hv_vscheduleMessageForReceiver(HvBase *c, const char *receiverName, const double delayMs, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  const int numElem = (int) hv_strlen(format);
+  HvMessage *m = HV_MESSAGE_ON_STACK(numElem);
+  msg_init(m, numElem, c->blockStartTimestamp + (hv_uint32_t) (hv_max_d(0.0, delayMs)*ctx_getSampleRate(c)/1000.0));
+  for (int i = 0; i < numElem; i++) {
+    switch (format[i]) {
+      case 'b': msg_setBang(m,i); break;
+      case 'f': msg_setFloat(m, i, (float) va_arg(ap, double)); break;
+      case 's': msg_setSymbol(m, i, (char *) va_arg(ap, char *)); break;
+      default: break;
+    }
+  }
+  ctx_scheduleMessageForReceiver(c, receiverName, m);
+
+  va_end(ap);
+}
+
+void hv_scheduleMessageForReceiver(HvBase *c, const char *receiverName, double delayMs, HvMessage *m) {
+  hv_assert(delayMs >= 0.0);
+  msg_setTimestamp(m, c->blockStartTimestamp + (hv_uint32_t) (delayMs*ctx_getSampleRate(c)/1000.0));
+  ctx_scheduleMessageForReceiver(c, receiverName, m);
+}
+
+HvTable *hv_getTableForName(HvBase *c, const char *tableName) {
+  return ctx_getTableForName(c, tableName);
+}
+
+void hv_cancelMessage(HvBase *c, HvMessage *m) {
+  ctx_cancelMessage(c, m, NULL);
+}
+
+double hv_getCurrentTime(HvBase *c) {
+  return ((double) c->blockStartTimestamp)/c->sampleRate;
+}
+
+void *hv_getUserData(HvBase *c) {
+  return ctx_getUserData(c);
+}
+
+void hv_setUserData(HvBase *c, void *userData) {
+  ctx_setUserData(c, userData);
+}
+
+void hv_setBasePath(HvBase *c, const char *basePath) {
+  ctx_setBasePath(c, basePath);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HeavyMath.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,645 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_MATH_H_
+#define _HEAVY_MATH_H_
+
+#include "Utils.h"
+
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/
+// https://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/ARM-NEON-Intrinsics.html
+// http://codesuppository.blogspot.co.uk/2015/02/sse2neonh-porting-guide-and-header-file.html
+
+static inline void __hv_zero_f(hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_setzero_ps();
+#elif HV_SIMD_SSE
+  *bOut = _mm_setzero_ps();
+#elif HV_SIMD_NEON
+  *bOut = vdupq_n_f32(0.0f);
+#else // HV_SIMD_NONE
+  *bOut = 0.0f;
+#endif
+}
+
+static inline void __hv_load_f(float *bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_load_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_load_ps(bIn);
+#elif HV_SIMD_NEON
+  *bOut = vld1q_f32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = *bIn;
+#endif
+}
+
+static inline void __hv_store_f(float *bOut, hv_bInf_t bIn) {
+#if HV_SIMD_AVX
+  _mm256_store_ps(bOut, bIn);
+#elif HV_SIMD_SSE
+  _mm_store_ps(bOut, bIn);
+#elif HV_SIMD_NEON
+  vst1q_f32(bOut, bIn);
+#else // HV_SIMD_NONE
+  *bOut = bIn;
+#endif
+}
+
+static inline void __hv_log_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_log_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_log_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_log_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = (bIn > 0.0f) ? hv_log_f(bIn) : 0.0f;
+#endif
+}
+
+static inline void __hv_log10_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_log10_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_log10_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_log10_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = (bIn > 0.0f) ? hv_log10_f(bIn) : 0.0f;
+#endif
+}
+
+static inline void __hv_log2_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_log2_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_log2_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_log2_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = (bIn > 0.0f) ? hv_log2_f(bIn) : 0.0f;
+#endif
+}
+
+// NOTE(mhroth): this is a pretty ghetto implementation
+static inline void __hv_cos_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_set_ps(
+      hv_cos_f(bIn[7]), hv_cos_f(bIn[6]), hv_cos_f(bIn[5]), hv_cos_f(bIn[4]),
+      hv_cos_f(bIn[3]), hv_cos_f(bIn[2]), hv_cos_f(bIn[1]), hv_cos_f(bIn[0]));
+#elif HV_SIMD_SSE
+  *bOut = _mm_set_ps(hv_cos_f(bIn[3]), hv_cos_f(bIn[2]), hv_cos_f(bIn[1]), hv_cos_f(bIn[0]));
+#elif HV_SIMD_NEON
+  *bOut = (float32x4_t) {hv_cos_f(bIn[0]), hv_cos_f(bIn[1]), hv_cos_f(bIn[2]), hv_cos_f(bIn[3])};
+#else // HV_SIMD_NONE
+  *bOut = hv_cos_f(bIn);
+#endif
+}
+
+static inline void __hv_acos_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_acos_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_acos_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_acos_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_acos_f(bIn);
+#endif
+}
+
+static inline void __hv_cosh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_cosh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_cosh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_cosh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_cosh_f(bIn);
+#endif
+}
+
+static inline void __hv_acosh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_acosh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_acosh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_acosh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_acosh_f(bIn);
+#endif
+}
+
+static inline void __hv_sin_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_sin_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_sin_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_sin_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_sin_f(bIn);
+#endif
+}
+
+static inline void __hv_asin_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_asin_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_asin_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_asin_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_asin_f(bIn);
+#endif
+}
+
+static inline void __hv_sinh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_sinh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_sinh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_sinh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_sinh_f(bIn);
+#endif
+}
+
+static inline void __hv_asinh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_asinh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_asinh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_asinh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_asinh_f(bIn);
+#endif
+}
+
+static inline void __hv_tan_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_tan_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_tan_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_tan_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_tan_f(bIn);
+#endif
+}
+
+static inline void __hv_atan_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_atan_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_atan_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_atan_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_atan_f(bIn);
+#endif
+}
+
+static inline void __hv_atan2_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_atan2_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_atan2_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_atan2_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_atan2_f(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_tanh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_tanh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_tanh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_tanh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_tanh_f(bIn);
+#endif
+}
+
+static inline void __hv_atanh_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_atanh_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_atanh_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_atanh_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_atanh_f(bIn);
+#endif
+}
+
+// NOTE(mhroth): use of sqrt is absolute and total MURDER. Make do with recipocal sqrt if possible!!
+static inline void __hv_sqrt_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_sqrt_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_sqrt_ps(bIn);
+#elif HV_SIMD_NEON
+#warning __hv_sqrt_f() numerical results may be inexact
+  *bOut = vrecpeq_f32(vrsqrteq_f32(bIn));
+#else // HV_SIMD_NONE
+  *bOut = hv_sqrt_f(bIn);
+#endif
+}
+
+static inline void __hv_rsqrt_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_rsqrt_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_rsqrt_ps(bIn);
+#elif HV_SIMD_NEON
+#warning __hv_rsqrt_f() numerical results may be inexact
+  *bOut = vrsqrteq_f32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = 1.0f/hv_sqrt_f(bIn);
+#endif
+}
+
+static inline void __hv_abs_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_andnot_ps(_mm256_set1_ps(-0.0f), bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_andnot_ps(_mm_set1_ps(-0.0f), bIn); // == 1 << 31
+#elif HV_SIMD_NEON
+  *bOut = vabsq_f32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = hv_abs_f(bIn);
+#endif
+}
+
+static inline void __hv_exp_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_exp_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_exp_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_exp_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = hv_exp_f(bIn);
+#endif
+}
+
+static inline void __hv_ceil_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_ceil_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_ceil_ps(bIn);
+#elif HV_SIMD_NEON
+#if __ARM_ARCH >= 8
+  *bOut = vrndpq_f32(bIn);
+#else
+#warning A slow NEON implementation of __hv_ceil_f() is being used because the necessary intrinsic cannot be found. It is only available in ARMv8.
+  *bOut = (float32x4_t) {hv_ceil_f(bIn[0]), hv_ceil_f(bIn[1]), hv_ceil_f(bIn[2]), hv_ceil_f(bIn[3])};
+#endif // vrndpq_f32
+#else // HV_SIMD_NONE
+  *bOut = hv_ceil_f(bIn);
+#endif
+}
+
+static inline void __hv_floor_f(hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_floor_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_floor_ps(bIn);
+#elif HV_SIMD_NEON
+#if __ARM_ARCH >= 8
+  *bOut = vrndmq_f32(bIn);
+#else
+#warning A slow NEON implementation of __hv_floor_f() is being used because the necessary intrinsic cannot be found. It is only available in ARMv8.
+  *bOut = (float32x4_t) {hv_floor_f(bIn[0]), hv_floor_f(bIn[1]), hv_floor_f(bIn[2]), hv_floor_f(bIn[3])};
+#endif // vrndmq_f32
+#else // HV_SIMD_NONE
+  *bOut = hv_floor_f(bIn);
+#endif
+}
+
+// __add~f
+static inline void __hv_add_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_add_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_add_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vaddq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 + bIn1;
+#endif
+}
+
+// __add~i
+static inline void __hv_add_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  __m128i x = _mm_add_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1));
+  __m128i y = _mm_add_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1));
+  *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_add_epi32(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vaddq_s32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 + bIn1;
+#endif
+}
+
+// __sub~f
+static inline void __hv_sub_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_sub_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_sub_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vsubq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 - bIn1;
+#endif
+}
+
+// __mul~f
+static inline void __hv_mul_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_mul_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_mul_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vmulq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 * bIn1;
+#endif
+}
+
+// __*~i
+static inline void __hv_mul_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  __m128i x = _mm_mullo_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1));
+  __m128i y = _mm_mullo_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1));
+  *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_mullo_epi32(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vmulq_s32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = bIn0 * bIn1;
+#endif
+}
+
+// __cast~if
+static inline void __hv_cast_if(hv_bIni_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cvtepi32_ps(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cvtepi32_ps(bIn);
+#elif HV_SIMD_NEON
+  *bOut = vcvtq_f32_s32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = (float) bIn;
+#endif
+}
+
+// __cast~fi
+static inline void __hv_cast_fi(hv_bInf_t bIn, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cvtps_epi32(bIn);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cvtps_epi32(bIn);
+#elif HV_SIMD_NEON
+  *bOut = vcvtq_s32_f32(bIn);
+#else // HV_SIMD_NONE
+  *bOut = (int) bIn;
+#endif
+}
+
+static inline void __hv_div_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_div_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_div_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+#warning __hv_div_f() numerical results may be inexact
+  *bOut = vmulq_f32(bIn0, vrecpeq_f32(bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn1 != 0.0f) ? (bIn0 / bIn1) : 0.0f;
+#endif
+}
+
+static inline void __hv_min_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_min_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_min_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vminq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = hv_min_f(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_min_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  __m128i x = _mm_min_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1));
+  __m128i y = _mm_min_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1));
+  *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_min_epi32(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vminq_s32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = hv_min_i(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_max_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_max_ps(bIn0, bIn1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_max_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vmaxq_f32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = hv_max_f(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_max_i(hv_bIni_t bIn0, hv_bIni_t bIn1, hv_bOuti_t bOut) {
+#if HV_SIMD_AVX
+  __m128i x = _mm_max_epi32(_mm256_castsi256_si128(bIn0), _mm256_castsi256_si128(bIn1));
+  __m128i y = _mm_max_epi32(_mm256_extractf128_si256(bIn0, 1), _mm256_extractf128_si256(bIn1, 1));
+  *bOut = _mm256_insertf128_si256(_mm256_castsi128_si256(x), y, 1);
+#elif HV_SIMD_SSE
+  *bOut = _mm_max_epi32(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vmaxq_s32(bIn0, bIn1);
+#else // HV_SIMD_NONE
+  *bOut = hv_max_i(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_pow_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_set_ps(
+      hv_pow_f(bIn0[7], bIn1[7]),
+      hv_pow_f(bIn0[6], bIn1[6]),
+      hv_pow_f(bIn0[5], bIn1[5]),
+      hv_pow_f(bIn0[4], bIn1[4]),
+      hv_pow_f(bIn0[3], bIn1[3]),
+      hv_pow_f(bIn0[2], bIn1[2]),
+      hv_pow_f(bIn0[1], bIn1[1]),
+      hv_pow_f(bIn0[0], bIn1[0]));
+#elif HV_SIMD_SSE
+  *bOut = _mm_set_ps(
+      hv_pow_f(bIn0[3], bIn1[3]),
+      hv_pow_f(bIn0[2], bIn1[2]),
+      hv_pow_f(bIn0[1], bIn1[1]),
+      hv_pow_f(bIn0[0], bIn1[0]));
+#elif HV_SIMD_NEON
+  *bOut = (float32x4_t) {
+      hv_pow_f(bIn0[0], bIn1[0]),
+      hv_pow_f(bIn0[1], bIn1[1]),
+      hv_pow_f(bIn0[2], bIn1[2]),
+      hv_pow_f(bIn0[3], bIn1[3])};
+#else // HV_SIMD_NONE
+  *bOut = hv_pow_f(bIn0, bIn1);
+#endif
+}
+
+static inline void __hv_gt_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_GT_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmpgt_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vcgtq_f32(bIn0, bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 > bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_gte_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_GE_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmpge_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vcgeq_f32(bIn0, bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 >= bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_lt_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_LT_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmplt_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vcltq_f32(bIn0, bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 < bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_lte_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_LE_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmple_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vcleq_f32(bIn0, bIn1));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 <= bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_neq_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_cmp_ps(bIn0, bIn1, _CMP_NEQ_OQ);
+#elif HV_SIMD_SSE
+  *bOut = _mm_cmpneq_ps(bIn0, bIn1);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vmvnq_u32(vceqq_f32(bIn0, bIn1)));
+#else // HV_SIMD_NONE
+  *bOut = (bIn0 != bIn1) ? 1.0f : 0.0f;
+#endif
+}
+
+static inline void __hv_xor_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_xor_f() not implemented
+#elif HV_SIMD_SSE
+#warning __hv_xor_f() not implemented
+#elif HV_SIMD_NEON
+#warning __hv_xor_f() not implemented
+#else // HV_SIMD_NONE
+  *bOut = (float) (((int) bIn0) ^ ((int) bIn1));
+#endif
+}
+
+static inline void __hv_and_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_and_ps(bIn1, bIn0);
+#elif HV_SIMD_SSE
+  *bOut = _mm_and_ps(bIn1, bIn0);
+#elif HV_SIMD_NEON
+  *bOut = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(bIn1), vreinterpretq_u32_f32(bIn0)));
+#else // HV_SIMD_NONE
+  if (bIn0 == 0.0f || bIn1 == 0.0f) *bOut = 0.0f;
+  else if (bIn0 == 1.0f) *bOut = bIn1;
+  else if (bIn1 == 1.0f) *bOut = bIn0;
+  else hv_assert(0); // TODO(mhroth): floating point & is pretty much a bad idea, only used for if~
+#endif
+}
+
+// bOut = (bIn0 * bIn1) + bIn2
+static inline void __hv_fma_f(hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bInf_t bIn2, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#if HV_SIMD_FMA
+  *bOut = _mm256_fmadd_ps(bIn0, bIn1, bIn2);
+#else
+  *bOut = _mm256_add_ps(_mm256_mul_ps(bIn0, bIn1), bIn2);
+#endif // HV_SIMD_FMA
+#elif HV_SIMD_SSE
+#if HV_SIMD_FMA
+  *bOut = _mm_fmadd_ps(bIn0, bIn1, bIn2);
+#else
+  *bOut = _mm_add_ps(_mm_mul_ps(bIn0, bIn1), bIn2);
+#endif // HV_SIMD_FMA
+#elif HV_SIMD_NEON
+#if __ARM_ARCH >= 8
+  *bOut = vfmaq_f32(bIn2, bIn0, bIn1);
+#else
+  // NOTE(mhroth): it turns out, fma SUUUUCKS on lesser ARM architectures
+  // But in fact ideally fma would be disabled in ir2c for ARM architectures.
+  // LLVM does a much better job handling fma than we do.
+  *bOut = vaddq_f32(vmulq_f32(bIn0, bIn1), bIn2);
+#endif
+#else // HV_SIMD_NONE
+  *bOut = hv_fma_f(bIn0, bIn1, bIn2);
+#endif
+}
+
+#endif // _HEAVY_MATH_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Heavy_bbb.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,241 @@
+
+/**
+ * Copyright (c) 2014,2015 Enzien Audio, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, and/or
+ * sublicense copies of the Software, strictly on a non-commercial basis,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * DO NOT MODIFY. THIS CODE IS MACHINE GENERATED BY THE SECTION6 HEAVY COMPILER.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "Utils.h"
+
+#if !HV_MSVC
+#pragma mark - Heavy Table
+#endif
+
+#ifndef _HEAVY_TABLE_H_
+#define _HEAVY_TABLE_H_
+
+typedef struct HvTable HvTable;
+
+/**
+ * Resizes the table to the given length. Length must be positive.
+ * Existing contents are copied to the new table. Remaining space is cleared.
+ * The change in byte-size of the table is returned. A value of zero indicates error.
+ */
+HV_EXPORT int hv_table_resize(HvTable *o, hv_uint32_t newLength);
+
+/** Returns a pointer to the raw buffer backing this table. DO NOT free it. */
+HV_EXPORT float *hv_table_getBuffer(HvTable *o);
+
+/** Returns the length of this table in samples. */
+HV_EXPORT int hv_table_getLength(HvTable *o);
+
+#endif // _HEAVY_TABLE_H_
+
+
+
+#if !HV_MSVC
+#pragma mark - Heavy Message
+#endif
+
+#ifndef _HEAVY_MESSAGE_H_
+#define _HEAVY_MESSAGE_H_
+
+HV_EXPORT typedef struct HvMessage HvMessage;
+
+/** Returns the byte size of a HvMessage with a number of elements on the heap. */
+HV_EXPORT hv_size_t hv_msg_getByteSize(int numElements);
+
+/** Create a HvMessage on the stack with a number of elements. This message MUST NOT be freed. */
+#define hv_msg_onStack(_n) ((HvMessage *) hv_alloca(hv_msg_getByteSize(_n)))
+
+/** Initialise a message with the number of elements and a timestamp (in milliseconds). */
+HV_EXPORT void hv_msg_init(HvMessage *m, int numElements, double timestamp);
+
+/** Returns the number of elements in this message. */
+HV_EXPORT int hv_msg_getNumElements(const HvMessage *const m);
+
+/** Returns the time at which this message exists (in milliseconds). */
+HV_EXPORT hv_uint32_t hv_msg_getTimestamp(const HvMessage *const m);
+
+/** Set the time at which this message should be executed (in milliseconds). */
+HV_EXPORT void hv_msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp);
+
+/** Returns true of the indexed element is a bang. False otherwise. Index is not bounds checked. */
+HV_EXPORT bool hv_msg_isBang(const HvMessage *const m, int i);
+
+/** Sets the indexed element to a bang. Index is not bounds checked. */
+HV_EXPORT void hv_msg_setBang(HvMessage *m, int i);
+
+/** Returns true of the indexed element is a float. False otherwise. Index is not bounds checked. */
+HV_EXPORT bool hv_msg_isFloat(const HvMessage *const m, int i);
+
+/** Returns the indexed element as a float value. Index is not bounds checked. */
+HV_EXPORT float hv_msg_getFloat(const HvMessage *const m, int i);
+
+/** Sets the indexed element to float value. Index is not bounds checked. */
+HV_EXPORT void hv_msg_setFloat(HvMessage *m, int i, float f);
+
+/** Returns true of the indexed element is a symbol. False otherwise. Index is not bounds checked. */
+HV_EXPORT bool hv_msg_isSymbol(const HvMessage *const m, int i);
+
+/** Returns the indexed element as a symbol value. Index is not bounds checked. */
+HV_EXPORT char *hv_msg_getSymbol(const HvMessage *const m, int i);
+
+/** Returns true of the indexed element is a hash. False otherwise. Index is not bounds checked. */
+HV_EXPORT bool hv_msg_isHash(const HvMessage *const m, int i);
+
+/** Returns the indexed element as a hash value. Index is not bounds checked. */
+HV_EXPORT unsigned int hv_msg_getHash(const HvMessage *const m, int i);
+
+/** Sets the indexed element to symbol value. Index is not bounds checked. */
+HV_EXPORT void hv_msg_setSymbol(HvMessage *m, int i, const char *s);
+
+/**
+ * Returns true if the message has the given format, in number of elements and type. False otherwise.
+ * Valid element types are:
+ * 'b': bang
+ * 'f': float
+ * 's': symbol
+ *
+ * For example, a message with three floats would have a format of "fff". A single bang is "b".
+ * A message with two symbols is "ss". These types can be mixed and matched in any way.
+ */
+HV_EXPORT bool hv_msg_hasFormat(const HvMessage *const m, const char *fmt);
+
+/**
+ * Returns a basic string representation of the message.
+ * The character array MUST be deallocated by the caller.
+ */
+HV_EXPORT char *hv_msg_toString(const HvMessage *const m);
+
+/** Copy a message onto the stack. The message persists. */
+HV_EXPORT HvMessage *hv_msg_copy(const HvMessage *const m);
+
+/** Free a copied message. */
+HV_EXPORT void hv_msg_free(HvMessage *m);
+
+#endif // _HEAVY_MESSAGE_H_
+
+
+
+#if !HV_MSVC
+#pragma mark - Heavy Patch
+#endif
+
+#ifndef _HEAVY_BBB_H_
+#define _HEAVY_BBB_H_
+
+typedef struct Hv_bbb Hv_bbb;
+
+/**
+ * Creates a new patch instance.
+ * Sample rate should be positive and in Hertz.
+ */
+HV_EXPORT Hv_bbb *hv_bbb_new(double sampleRate);
+
+/**
+ * Creates a new patch instance.
+ * Sample rate should be positive and in Hertz.
+ * Pool size is in kilobytes, and determines the maximum amount of memory
+ *   allocated to messages at any time. By default this is 10.
+ */
+HV_EXPORT Hv_bbb *hv_bbb_new_with_pool(double sampleRate, int poolKb);
+
+/** Frees a patch instance. */
+HV_EXPORT void hv_bbb_free(Hv_bbb *c);
+
+/** Processes one block of samples for a patch instance. The buffer format is an array of float channel arrays. */
+HV_EXPORT int hv_bbb_process(Hv_bbb *c, float **const inputBuffers, float **const outputBuffers, int n4);
+
+/** Processes one block of samples for a patch instance. The buffer format is an uninterleaved float array of channels. */
+HV_EXPORT int hv_bbb_process_inline(Hv_bbb *c, float *const inputBuffers, float *const outputBuffers, int n4);
+
+/** Processes one block of samples for a patch instance. The buffer format is an interleaved short array of channels. */
+HV_EXPORT int hv_bbb_process_inline_short(Hv_bbb *c, short *const inputBuffers, short *const outputBuffers, int n4);
+#endif // _HEAVY_BBB_H_
+
+
+
+#if !HV_MSVC
+#pragma mark - Heavy Common
+#endif
+
+#ifndef _HEAVY_COMMON_H_
+#define _HEAVY_COMMON_H_
+
+typedef void Heavy;
+
+/** Returns the sample rate with which this patch has been configured. */
+HV_EXPORT double hv_getSampleRate(Heavy *c);
+
+/** Returns the number of input channels with which this patch has been configured. */
+HV_EXPORT int hv_getNumInputChannels(Heavy *c);
+
+/** Returns the number of output channels with which this patch has been configured. */
+HV_EXPORT int hv_getNumOutputChannels(Heavy *c);
+
+/** Set the print hook. The function is called whenever a message is sent to a print object. */
+HV_EXPORT void hv_setPrintHook(Heavy *c,
+    void (*f)(double timestamp, const char *printName, const char *message, void *userData));
+
+/**
+ * Set the send hook. The function is called whenever a message is sent to any send object.
+ * Messages returned by this function should NEVER be freed. If the message must persist, call
+ * hv_msg_copy() first.
+ */
+HV_EXPORT void hv_setSendHook(Heavy *c, void (*f)(double timestamp, const char *receiverName, const HvMessage *const m, void *userData));
+
+HV_EXPORT void hv_vscheduleMessageForReceiver(
+    Heavy *c, const char *receiverName, double delayMs, const char *format, ...);
+
+HV_EXPORT void hv_scheduleMessageForReceiver(Heavy *c, const char *receiverName, double delayMs, HvMessage *m);
+
+/** Cancels a previously scheduled message. */
+HV_EXPORT void hv_cancelMessage(Heavy *c, HvMessage *m);
+
+/** Returns a table object given its name. NULL if no table with that name exists. */
+HV_EXPORT HvTable *hv_getTableForName(Heavy *c, const char *tableName);
+
+/** Returns the current patch time in milliseconds. */
+HV_EXPORT double hv_getCurrentTime(Heavy *c);
+
+/** Sets a user-definable value. This value is never manipulated by Heavy. */
+HV_EXPORT void hv_setUserData(Heavy *c, void *userData);
+
+/** Returns the user-defined data. */
+HV_EXPORT void *hv_getUserData(Heavy *c);
+
+/** Define the base path of the patch. Used as the root path to locate assets. */
+HV_EXPORT void hv_setBasePath(Heavy *c, const char *basePath);
+
+/** Returns the read-only user-assigned name of this patch. */
+HV_EXPORT const char *hv_getName(Heavy *c);
+
+#endif // _HEAVY_COMMON_H_
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HvBase.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "HvBase.h"
+
+void ctx_setBasePath(HvBase *const _c, const char *basePath) {
+  hv_free(_c->basePath);
+  if (basePath != NULL) {
+    hv_size_t len = (hv_size_t) hv_strlen(basePath);
+    _c->basePath = (char *) hv_malloc((len+1)*sizeof(char));
+    hv_strncpy(_c->basePath, basePath, len);
+  }
+}
+
+void ctx_cancelMessage(HvBase *_c, HvMessage *m, void (*sendMessage)(HvBase *, int, const HvMessage *)) {
+  mq_removeMessage(&_c->mq, m, sendMessage);
+}
+
+void ctx_scheduleMessageForReceiverV(HvBase *const _c, const char *name,
+    const hv_uint32_t timestamp, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  const int numElem = (int) hv_strlen(format);
+  HvMessage *m = HV_MESSAGE_ON_STACK(numElem);
+  msg_init(m, numElem, timestamp);
+  for (int i = 0; i < numElem; i++) {
+    switch (format[i]) {
+      case 'b': msg_setBang(m,i); break;
+      case 'f': msg_setFloat(m, i, (float) va_arg(ap, double)); break;
+      case 's': msg_setSymbol(m, i, (char *) va_arg(ap, char *)); break;
+      default: break;
+    }
+  }
+  _c->f_scheduleMessageForReceiver(_c, name, m);
+
+  va_end(ap);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HvBase.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_BASE_H_
+#define _HEAVY_BASE_H_
+
+#include "MessageQueue.h"
+#include "Utils.h"
+
+#define Base(_x) ((HvBase *) _x)
+
+typedef struct HvBase {
+  int numInputChannels;
+  int numOutputChannels;
+  double sampleRate;
+  hv_uint32_t blockStartTimestamp;
+  unsigned int numBytes; // the total number of bytes allocated for this patch
+  void (*f_scheduleMessageForReceiver)(struct HvBase *const, const char *, HvMessage *);
+  struct HvTable *(*f_getTableForHash)(struct HvBase *const, hv_uint32_t);
+  MessageQueue mq;
+  void (*printHook)(double, const char *, const char *, void *);
+  void (*sendHook)(double, const char *, const HvMessage *const, void *);
+  char *basePath;
+  void *userData;
+  const char *name;
+} HvBase;
+
+/**
+ * Schedule a message in the message queue according to its timestamp.
+ * The copy of the message added to the queue is returned.
+ */
+static inline HvMessage *ctx_scheduleMessage(HvBase *_c, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *), int outletIndex) {
+  return mq_addMessageByTimestamp(&_c->mq, (HvMessage *) m, outletIndex, sendMessage);
+}
+
+static inline void ctx_scheduleMessageForReceiver(HvBase *const _c,
+    const char *name, HvMessage *m) {
+  _c->f_scheduleMessageForReceiver(_c, name, m);
+}
+
+void ctx_scheduleMessageForReceiverV(HvBase *const _c, const char *name,
+    const hv_uint32_t timestamp, const char *format, ...);
+
+void ctx_cancelMessage(HvBase *_c, HvMessage *m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *));
+
+static inline int ctx_millisecondsToSamples(HvBase *_c, float timeInMs) {
+  return (int) (timeInMs * _c->sampleRate / 1000.0);
+}
+
+static inline double ctx_samplesToMilliseconds(HvBase *_c, int samples) {
+  return 1000.0 * samples / _c->sampleRate;
+}
+
+static inline double ctx_getSampleRate(HvBase *_c) {
+  return _c->sampleRate;
+}
+
+static inline int ctx_getNumInputChannels(HvBase *_c) {
+  return _c->numInputChannels;
+}
+
+static inline int ctx_getNumOutputChannels(HvBase *_c) {
+  return _c->numOutputChannels;
+}
+
+static inline const char *ctx_getName(HvBase *_c) {
+  return _c->name;
+}
+
+/** Returns the first sample of the block. */
+static inline hv_uint32_t ctx_getBlockStartTimestamp(HvBase *_c) {
+  return _c->blockStartTimestamp;
+}
+
+static inline void ctx_setPrintHook(HvBase *const _c, void (*f)(double,
+    const char *, const char *, void *)) {
+  _c->printHook = f;
+}
+
+static inline void ctx_setSendHook(HvBase *const _c, void (*f)(double, const char *, const HvMessage *const, void *)) {
+  _c->sendHook = f;
+}
+
+static inline void *ctx_getUserData(HvBase *const _c) {
+  return _c->userData;
+}
+
+static inline void ctx_setUserData(HvBase *const _c, void *userData) {
+  _c->userData = userData;
+}
+
+void ctx_setBasePath(HvBase *const _c, const char *basePath);
+
+static inline const char *ctx_getBasePath(HvBase *const _c) {
+  return _c->basePath;
+}
+
+static inline struct HvTable *ctx_getTableForHash(HvBase *const _c, hv_uint32_t h) {
+  return _c->f_getTableForHash(_c, h);
+}
+
+static inline struct HvTable *ctx_getTableForName(HvBase *const _c, const char *tableName) {
+  return ctx_getTableForHash(_c, msg_symbolToHash(tableName));
+}
+
+/** Returns the total number of bytes allocated for this patch. */
+static inline unsigned int ctx_getNumBytes(HvBase *_c) {
+  return _c->numBytes;
+}
+
+#endif // _HEAVY_BASE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HvContext_bbb.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,339 @@
+
+/**
+ * Copyright (c) 2014,2015 Enzien Audio, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, and/or
+ * sublicense copies of the Software, strictly on a non-commercial basis,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * DO NOT MODIFY. THIS CODE IS MACHINE GENERATED BY THE SECTION6 HEAVY COMPILER.
+ */
+
+/*
+ * System Includes
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <string.h>
+#include <stdarg.h>
+#include "HvContext_bbb.h"
+#include "HeavyMath.h"
+
+
+/*
+ * Function Declarations
+ */
+static void cBinop_62MLs_sendMessage(HvBase *, int, const HvMessage *const);
+static void cUnop_Rm4T9_sendMessage(HvBase *, int, const HvMessage *const);
+static void cRandom_Uxs9y_sendMessage(HvBase *, int, const HvMessage *const);
+static void cLoadbang_XJMP6_sendMessage(HvBase *, int, const HvMessage *const);
+static void cMsg_eMw6t_sendMessage(HvBase *, int, const HvMessage *const);
+static void cBinop_vHnCM_sendMessage(HvBase *, int, const HvMessage *const);
+static void cBinop_PmuD1_sendMessage(HvBase *, int, const HvMessage *const);
+static void cBinop_lT4qw_sendMessage(HvBase *, int, const HvMessage *const);
+static void cBinop_vpZDi_sendMessage(HvBase *, int, const HvMessage *const);
+static void cMsg_zpcIL_sendMessage(HvBase *, int, const HvMessage *const);
+static void cMsg_pfnj7_sendMessage(HvBase *, int, const HvMessage *const);
+static void cSystem_lJZJR_sendMessage(HvBase *, int, const HvMessage *const);
+static void cVar_cPxQc_sendMessage(HvBase *, int, const HvMessage *const);
+static void cBinop_1u9M5_sendMessage(HvBase *, int, const HvMessage *const);
+static void cLoadbang_AXnu9_sendMessage(HvBase *, int, const HvMessage *const);
+
+
+
+/*
+ * Static Helper Functions
+ */
+
+static void ctx_intern_scheduleMessageForReceiver(
+    HvBase *const _c, const char *name, HvMessage *m) {
+  switch (msg_symbolToHash(name)) {
+    default: return;
+  }
+}
+
+static struct HvTable *ctx_intern_getTableForHash(HvBase *const _c, hv_uint32_t h) {
+  switch (h) {
+    default: return NULL;
+  }
+}
+
+
+
+/*
+ * Context Include and Implementatons
+ */
+
+Hv_bbb *hv_bbb_new_with_pool(double sampleRate, int poolKb) {
+  hv_assert(sampleRate > 0.0); // can't initialise with sampling rate of 0
+  hv_assert(poolKb >= 1); // a message pool of some reasonable size is always needed
+  Hv_bbb *const _c = (Hv_bbb *) hv_malloc(sizeof(Hv_bbb));
+
+  Base(_c)->numInputChannels = 0;
+  Base(_c)->numOutputChannels = 2;
+  Base(_c)->sampleRate = sampleRate;
+  Base(_c)->blockStartTimestamp = 0;
+  Base(_c)->f_scheduleMessageForReceiver = &ctx_intern_scheduleMessageForReceiver;
+  Base(_c)->f_getTableForHash = &ctx_intern_getTableForHash;
+  mq_initWithPoolSize(&Base(_c)->mq, poolKb);
+  Base(_c)->basePath = NULL;
+  Base(_c)->printHook = NULL;
+  Base(_c)->sendHook = NULL;
+  Base(_c)->userData = NULL;
+  Base(_c)->name = "bbb";
+
+  Base(_c)->numBytes = sizeof(Hv_bbb);
+  Base(_c)->numBytes += sVari_init(&_c->sVari_ecpIx, 0, 0, false);
+  Base(_c)->numBytes += sVarf_init(&_c->sVarf_VF9rD, 0.0f, 0.0f, false);
+  Base(_c)->numBytes += sVarf_init(&_c->sVarf_0bFmM, 0.0f, 0.0f, false);
+  Base(_c)->numBytes += sRPole_init(&_c->sRPole_WxgWS);
+  Base(_c)->numBytes += sPhasor_k_init(&_c->sPhasor_YcHM3, 880.0f, sampleRate);
+  Base(_c)->numBytes += sDel1_init(&_c->sDel1_FfVih);
+  Base(_c)->numBytes += sSamphold_init(&_c->sSamphold_hq9sm);
+  Base(_c)->numBytes += sPhasor_init(&_c->sPhasor_n1TcS, sampleRate);
+  Base(_c)->numBytes += cBinop_init(&_c->cBinop_62MLs, 8388610.0f); // __mul
+  Base(_c)->numBytes += cRandom_init(&_c->cRandom_Uxs9y, -1512500956);
+  Base(_c)->numBytes += cBinop_init(&_c->cBinop_vHnCM, 1.0f); // __min
+  Base(_c)->numBytes += cBinop_init(&_c->cBinop_PmuD1, 0.0f); // __max
+  Base(_c)->numBytes += cBinop_init(&_c->cBinop_lT4qw, 0.0f); // __mul
+  Base(_c)->numBytes += cVar_init_f(&_c->cVar_cPxQc, 1.0f);
+
+  // loadbang
+  ctx_scheduleMessage(Base(_c), msg_initWithBang(HV_MESSAGE_ON_STACK(1), 0), &cLoadbang_AXnu9_sendMessage, 0);
+  ctx_scheduleMessage(Base(_c), msg_initWithBang(HV_MESSAGE_ON_STACK(1), 0), &cLoadbang_XJMP6_sendMessage, 0);
+
+  return _c;
+}
+
+Hv_bbb *hv_bbb_new(double sampleRate) {
+  return hv_bbb_new_with_pool(sampleRate, 10); // default to 10KB MessagePool
+}
+
+void hv_bbb_free(Hv_bbb *_c) {
+
+  hv_free(Base(_c)->basePath);
+  mq_free(&Base(_c)->mq); // free queue after all objects have been freed, messages may be cancelled
+
+  hv_free(_c);
+}
+
+
+
+/*
+ * Static Function Implementation
+ */
+static void cBinop_62MLs_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cUnop_onMessage(_c, HV_UNOP_FLOOR, m, &cUnop_Rm4T9_sendMessage);
+}
+
+static void cUnop_Rm4T9_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cMsg_eMw6t_sendMessage(_c, 0, m);
+}
+
+static void cRandom_Uxs9y_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cBinop_onMessage(_c, &Context(_c)->cBinop_62MLs, HV_BINOP_MULTIPLY, 0, m, &cBinop_62MLs_sendMessage);
+}
+
+static void cLoadbang_XJMP6_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cRandom_onMessage(_c, &Context(_c)->cRandom_Uxs9y, 0, m, &cRandom_Uxs9y_sendMessage);
+}
+
+static void cMsg_eMw6t_sendMessage(HvBase *_c, int letIn, const HvMessage *const n) {
+  HvMessage *m = NULL;
+  m = HV_MESSAGE_ON_STACK(2);
+  msg_init(m, 2, msg_getTimestamp(n));
+  msg_setElementToFrom(m, 0, n, 0);
+  msg_setFloat(m, 1, 1.0f);
+  sVari_onMessage(_c, &Context(_c)->sVari_ecpIx, m);
+}
+
+static void cBinop_vHnCM_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cBinop_onMessage(_c, &Context(_c)->cBinop_PmuD1, HV_BINOP_MAX, 0, m, &cBinop_PmuD1_sendMessage);
+}
+
+static void cBinop_PmuD1_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cBinop_k_onMessage(_c, NULL, HV_BINOP_SUBTRACT, 1.0f, 0, m, &cBinop_1u9M5_sendMessage);
+  sVarf_onMessage(_c, &Context(_c)->sVarf_VF9rD, m);
+}
+
+static void cBinop_lT4qw_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cBinop_onMessage(_c, &Context(_c)->cBinop_vHnCM, HV_BINOP_MIN, 0, m, &cBinop_vHnCM_sendMessage);
+}
+
+static void cBinop_vpZDi_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cBinop_onMessage(_c, &Context(_c)->cBinop_lT4qw, HV_BINOP_MULTIPLY, 1, m, &cBinop_lT4qw_sendMessage);
+}
+
+static void cMsg_zpcIL_sendMessage(HvBase *_c, int letIn, const HvMessage *const n) {
+  HvMessage *m = NULL;
+  m = HV_MESSAGE_ON_STACK(2);
+  msg_init(m, 2, msg_getTimestamp(n));
+  msg_setFloat(m, 0, 6.28319f);
+  msg_setElementToFrom(m, 1, n, 0);
+  cBinop_k_onMessage(_c, NULL, HV_BINOP_DIVIDE, 0.0f, 0, m, &cBinop_vpZDi_sendMessage);
+}
+
+static void cMsg_pfnj7_sendMessage(HvBase *_c, int letIn, const HvMessage *const n) {
+  HvMessage *m = NULL;
+  m = HV_MESSAGE_ON_STACK(1);
+  msg_init(m, 1, msg_getTimestamp(n));
+  msg_setSymbol(m, 0, "samplerate");
+  cSystem_onMessage(_c, NULL, 0, m, &cSystem_lJZJR_sendMessage);
+}
+
+static void cSystem_lJZJR_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cMsg_zpcIL_sendMessage(_c, 0, m);
+}
+
+static void cVar_cPxQc_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cBinop_onMessage(_c, &Context(_c)->cBinop_lT4qw, HV_BINOP_MULTIPLY, 0, m, &cBinop_lT4qw_sendMessage);
+}
+
+static void cBinop_1u9M5_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  sVarf_onMessage(_c, &Context(_c)->sVarf_0bFmM, m);
+}
+
+static void cLoadbang_AXnu9_sendMessage(HvBase *_c, int letIn, const HvMessage *const m) {
+  cMsg_pfnj7_sendMessage(_c, 0, m);
+  cVar_onMessage(_c, &Context(_c)->cVar_cPxQc, 0, m, &cVar_cPxQc_sendMessage);
+}
+
+
+
+
+/*
+ * Context Process Implementation
+ */
+
+int hv_bbb_process(Hv_bbb *const _c, float **const inputBuffers, float **const outputBuffers, int nx) {
+  const int n4 = nx & ~HV_N_SIMD_MASK; // ensure that the block size is a multiple of HV_N_SIMD
+
+  // temporary signal vars
+  hv_bufferf_t Bf0, Bf1, Bf2, Bf3, Bf4;
+  hv_bufferi_t Bi0, Bi1;
+
+  // input and output vars
+  hv_bufferf_t O0, O1;
+
+  // declare and init the zero buffer
+  hv_bufferf_t ZERO; __hv_zero_f(VOf(ZERO));
+
+  hv_uint32_t nextBlock = Base(_c)->blockStartTimestamp;
+  for (int n = 0; n < n4; n += HV_N_SIMD) {
+
+    // process all of the messages for this block
+    nextBlock += HV_N_SIMD;
+    while (mq_hasMessageBefore(&Base(_c)->mq, nextBlock)) {
+      MessageNode *const node = mq_peek(&Base(_c)->mq);
+      node->sendMessage(Base(_c), node->let, node->m);
+      mq_pop(&Base(_c)->mq);
+    }
+
+    
+
+    // zero output buffers
+    __hv_zero_f(VOf(O0));
+    __hv_zero_f(VOf(O1));
+
+    // process all signal functions
+    __hv_var_i(&_c->sVari_ecpIx, VOi(Bi0));
+    __hv_var_k_i(VOi(Bi1), 16807, 16807, 16807, 16807, 16807, 16807, 16807, 16807, 0);
+    __hv_mul_i(VIi(Bi0), VIi(Bi1), VOi(Bi1));
+    __hv_cast_if(VIi(Bi1), VOf(Bf0));
+    __hv_var_k_f(VOf(Bf1), 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 4.65661e-10f, 0);
+    __hv_mul_f(VIf(Bf0), VIf(Bf1), VOf(Bf1));
+    sVarseti_process(&_c->sVari_ecpIx, VIi(Bi1));
+    __hv_var_f(&_c->sVarf_VF9rD, VOf(Bf0));
+    __hv_mul_f(VIf(Bf1), VIf(Bf0), VOf(Bf0));
+    __hv_var_f(&_c->sVarf_0bFmM, VOf(Bf1));
+    __hv_rpole_f(&_c->sRPole_WxgWS, VIf(Bf0), VIf(Bf1), VOf(Bf1));
+    __hv_var_k_f(VOf(Bf0), 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 1000000.0f, 0);
+    __hv_mul_f(VIf(Bf1), VIf(Bf0), VOf(Bf0));
+    __hv_phasor_k_f(&_c->sPhasor_YcHM3, VOf(Bf1));
+    __hv_del1_f(&_c->sDel1_FfVih, VIf(Bf1), VOf(Bf2));
+    __hv_lt_f(VIf(Bf1), VIf(Bf2), VOf(Bf2));
+    __hv_samphold_f(&_c->sSamphold_hq9sm, VIf(Bf0), VIf(Bf2), VOf(Bf2));
+    __hv_phasor_f(&_c->sPhasor_n1TcS, VIf(Bf2), VOf(Bf2));
+    __hv_var_k_f(VOf(Bf0), 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0);
+    __hv_sub_f(VIf(Bf2), VIf(Bf0), VOf(Bf0));
+    __hv_abs_f(VIf(Bf0), VOf(Bf0));
+    __hv_var_k_f(VOf(Bf2), 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0);
+    __hv_sub_f(VIf(Bf0), VIf(Bf2), VOf(Bf2));
+    __hv_var_k_f(VOf(Bf0), 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 6.28319f, 0);
+    __hv_mul_f(VIf(Bf2), VIf(Bf0), VOf(Bf0));
+    __hv_mul_f(VIf(Bf0), VIf(Bf0), VOf(Bf2));
+    __hv_mul_f(VIf(Bf0), VIf(Bf2), VOf(Bf1));
+    __hv_mul_f(VIf(Bf1), VIf(Bf2), VOf(Bf2));
+    __hv_var_k_f(VOf(Bf3), 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0.00784314f, 0);
+    __hv_var_k_f(VOf(Bf4), 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0.166667f, 0);
+    __hv_mul_f(VIf(Bf1), VIf(Bf4), VOf(Bf4));
+    __hv_sub_f(VIf(Bf0), VIf(Bf4), VOf(Bf4));
+    __hv_fma_f(VIf(Bf2), VIf(Bf3), VIf(Bf4), VOf(Bf4));
+    __hv_var_k_f(VOf(Bf3), 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0);
+    __hv_mul_f(VIf(Bf4), VIf(Bf3), VOf(Bf3));
+    __hv_add_f(VIf(Bf3), VIf(O0), VOf(O0));
+    __hv_add_f(VIf(Bf3), VIf(O1), VOf(O1));
+
+    // save output vars to output buffer
+    __hv_store_f(outputBuffers[0]+n, VIf(O0));
+    __hv_store_f(outputBuffers[1]+n, VIf(O1));
+  }
+
+  Base(_c)->blockStartTimestamp = nextBlock;
+
+  return n4; // return the number of frames processed
+}
+
+int hv_bbb_process_inline(Hv_bbb *c, float *const inputBuffers, float *const outputBuffers, int n4) {
+  hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD
+  int i = ctx_getNumInputChannels(Base(c));
+  float **bIn = (float **) hv_alloca(i*sizeof(float *));
+  while (i--) bIn[i] = inputBuffers+(i*n4);
+
+  i = ctx_getNumOutputChannels(Base(c));
+  float **bOut = (float **) hv_alloca(i*sizeof(float *));
+  while (i--) bOut[i] = outputBuffers+(i*n4);
+
+  int n = hv_bbb_process(c, bIn, bOut, n4);
+  return n;
+}
+
+int hv_bbb_process_inline_short(Hv_bbb *c, short *const inputBuffers, short *const outputBuffers, int n4) {
+  hv_assert(!(n4 & HV_N_SIMD_MASK)); // ensure that n4 is a multiple of HV_N_SIMD
+  int numChannels = ctx_getNumInputChannels(Base(c));
+  float *bIn = (float *) hv_alloca(numChannels*n4*sizeof(float));
+  for (int i = 0; i < numChannels; ++i) {
+    for (int j = 0; j < n4; ++j) {
+      bIn[i*n4+j] = ((float) inputBuffers[i+numChannels*j]) * 0.00003051757813f;
+    }
+  }
+
+  numChannels = ctx_getNumOutputChannels(Base(c));
+  float *bOut = (float *) hv_alloca(numChannels*n4*sizeof(float));
+
+  int n = hv_bbb_process_inline(c, bIn, bOut, n4);
+
+  for (int i = 0; i < numChannels; ++i) {
+    for (int j = 0; j < n4; ++j) {
+      outputBuffers[i+numChannels*j] = (short) (bOut[i*n4+j] * 32767.0f);
+    }
+  }
+
+  return n;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HvContext_bbb.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,69 @@
+
+/**
+ * Copyright (c) 2014,2015 Enzien Audio, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, and/or
+ * sublicense copies of the Software, strictly on a non-commercial basis,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * DO NOT MODIFY. THIS CODE IS MACHINE GENERATED BY THE SECTION6 HEAVY COMPILER.
+ */
+
+#ifndef _HEAVYCONTEXT_BBB_H_
+#define _HEAVYCONTEXT_BBB_H_
+
+#include "HvBase.h"
+
+#define Context(_x) ((Hv_bbb *) (_x))
+
+// object includes
+#include "ControlSystem.h"
+#include "SignalVar.h"
+#include "SignalSamphold.h"
+#include "HeavyMath.h"
+#include "ControlBinop.h"
+#include "ControlVar.h"
+#include "ControlRandom.h"
+#include "SignalDel1.h"
+#include "SignalPhasor.h"
+#include "ControlUnop.h"
+#include "SignalRPole.h"
+
+typedef struct Hv_bbb {
+  HvBase base;
+
+  // objects
+  SignalVari sVari_ecpIx;
+  SignalVarf sVarf_VF9rD;
+  SignalVarf sVarf_0bFmM;
+  SignalRPole sRPole_WxgWS;
+  SignalPhasor sPhasor_YcHM3;
+  SignalDel1 sDel1_FfVih;
+  SignalSamphold sSamphold_hq9sm;
+  SignalPhasor sPhasor_n1TcS;
+  ControlBinop cBinop_62MLs;
+  ControlRandom cRandom_Uxs9y;
+  ControlBinop cBinop_vHnCM;
+  ControlBinop cBinop_PmuD1;
+  ControlBinop cBinop_lT4qw;
+  ControlBinop cBinop_vpZDi;
+  ControlVar cVar_cPxQc;
+  ControlBinop cBinop_1u9M5;
+} Hv_bbb;
+
+#endif // _HEAVYCONTEXT_BBB_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HvMessage.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,335 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "HvMessage.h"
+
+HvMessage *msg_init(HvMessage *m, hv_size_t numElements, hv_uint32_t timestamp) {
+  m->timestamp = timestamp;
+  m->numElements = (hv_uint16_t) numElements;
+  m->numBytes = (hv_uint16_t) msg_getByteSize(numElements);
+  return m;
+}
+
+HvMessage *msg_initWithFloat(HvMessage *m, hv_uint32_t timestamp, float f) {
+  m->timestamp = timestamp;
+  m->numElements = 1;
+  m->numBytes = sizeof(HvMessage);
+  msg_setFloat(m, 0, f);
+  return m;
+}
+
+HvMessage *msg_initWithBang(HvMessage *m, hv_uint32_t timestamp) {
+  m->timestamp = timestamp;
+  m->numElements = 1;
+  m->numBytes = sizeof(HvMessage);
+  msg_setBang(m, 0);
+  return m;
+}
+
+HvMessage *msg_initWithSymbol(HvMessage *m, hv_uint32_t timestamp, char *s) {
+  m->timestamp = timestamp;
+  m->numElements = 1;
+  m->numBytes = sizeof(HvMessage);
+  msg_setSymbol(m, 0, s);
+  return m;
+}
+
+HvMessage *msg_initWithHash(HvMessage *m, hv_uint32_t timestamp, hv_uint32_t h) {
+  m->timestamp = timestamp;
+  m->numElements = 1;
+  m->numBytes = sizeof(HvMessage);
+  msg_setHash(m, 0, h);
+  return m;
+}
+
+HvMessage *msg_initV(HvMessage *const m, const hv_uint32_t timestamp, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  const int numElem = (int) hv_strlen(format);
+  msg_init(m, numElem, timestamp);
+  for (int i = 0; i < numElem; i++) {
+    switch (format[i]) {
+      case 'b': msg_setBang(m,i); break;
+      case 'f': msg_setFloat(m, i, (float) va_arg(ap, double)); break;
+      case 's': msg_setSymbol(m, i, (char *) va_arg(ap, char *)); break;
+      case 'h': // hash not supported
+      default: break;
+    }
+  }
+  va_end(ap);
+
+  return m;
+}
+
+hv_size_t msg_getNumHeapBytes(const HvMessage *m) {
+  // get the size of all symbol elements
+  hv_size_t rsizeofsym = 0;
+  for (int i = 0; i < msg_getNumElements(m); ++i) {
+    if (msg_isSymbol(m,i)) {
+      rsizeofsym += (hv_size_t) hv_strlen(msg_getSymbol(m,i)) + 1; // +1 to allow for trailing '\0'
+    }
+  }
+
+  // the total byte size on the heap
+  return (msg_getByteSize(msg_getNumElements(m)) + rsizeofsym);
+}
+
+void msg_copyToBuffer(const HvMessage *m, char *buffer, hv_size_t len) {
+  HvMessage *r = (HvMessage *) buffer;
+
+  // assert that the message is not already larger than the length of the buffer
+  hv_assert(msg_getNumBytes(m) <= len);
+
+  // copy the basic message to the buffer
+  hv_memcpy(r, m, msg_getNumBytes(m));
+
+  hv_size_t len_r = msg_getNumBytes(m);
+
+  char *p = buffer + msg_getByteSize(msg_getNumElements(m)); // points to the end of the base message
+  for (int i = 0; i < msg_getNumElements(m); ++i) {
+    if (msg_isSymbol(m,i)) {
+      const hv_size_t symLen = (hv_size_t) hv_strlen(msg_getSymbol(m,i)) + 1; // include the trailing null char
+      hv_assert(len_r + symLen <= len); // stay safe!
+      hv_strncpy(p, msg_getSymbol(m,i), symLen);
+      msg_setSymbol(r, i, p);
+      p += symLen;
+      len_r += symLen;
+    }
+  }
+
+  r->numBytes = (hv_uint16_t) len_r; // update the message size in memory
+}
+
+// the message is serialised such that all symbol elements are placed in order at the end of the buffer
+HvMessage *msg_copy(const HvMessage *m) {
+  const hv_size_t heapSize = msg_getNumHeapBytes(m);
+  char *r = (char *) hv_malloc(heapSize);
+  msg_copyToBuffer(m, r, heapSize);
+  return (HvMessage *) r;
+}
+
+void msg_free(HvMessage *m) {
+  hv_free(m); // because heap messages are serialised in memory, a simple call to free releases the message
+}
+
+bool msg_hasFormat(const HvMessage *m, const char *fmt) {
+  if (fmt == NULL) return false;
+  if (msg_getNumElements(m) != hv_strlen(fmt)) return false;
+  for (int i = 0; i < msg_getNumElements(m); i++) {
+    switch (fmt[i]) {
+      case 'b': if (!msg_isBang(m, i)) return false; break;
+      case 'f': if (!msg_isFloat(m, i)) return false; break;
+      case 's': if (!msg_isSymbol(m, i)) return false; break;
+      case 'h': if (!msg_isHash(m, i)) return false; break;
+      default: return false;
+    }
+  }
+  return true;
+}
+
+bool msg_compareSymbol(const HvMessage *m, int i, const char *s) {
+  switch (msg_getType(m,i)) {
+    case SYMBOL: return !hv_strcmp(msg_getSymbol(m, i), s);
+    case HASH: return (msg_getHash(m,i) == msg_symbolToHash(s));
+    default: return false;
+  }
+}
+
+bool msg_equalsElement(const HvMessage *m, int i_m, const HvMessage *n, int i_n) {
+  if (i_m < msg_getNumElements(m) && i_n < msg_getNumElements(n)) {
+    if (msg_getType(m, i_m) == msg_getType(n, i_n)) {
+      switch (msg_getType(m, i_m)) {
+        case BANG: return true;
+        case FLOAT: return (msg_getFloat(m, i_m) == msg_getFloat(n, i_n));
+        case SYMBOL: return msg_compareSymbol(m, i_m, msg_getSymbol(n, i_n));
+        case HASH: return msg_getHash(m,i_m) == msg_getHash(n,i_n);
+        default: break;
+      }
+    }
+  }
+  return false;
+}
+
+void msg_setElementToFrom(HvMessage *n, int i_n, const HvMessage *const m, int i_m) {
+  switch (msg_getType(m, i_m)) {
+    case BANG: msg_setBang(n, i_n); break;
+    case FLOAT: msg_setFloat(n, i_n, msg_getFloat(m, i_m)); break;
+    case SYMBOL: msg_setSymbol(n, i_n, msg_getSymbol(m, i_m)); break;
+    case HASH: msg_setHash(n, i_n, msg_getHash(m, i_m));
+    default: break;
+  }
+}
+
+hv_uint32_t msg_symbolToHash(const char *s) {
+  // this hash is based MurmurHash2
+  // http://en.wikipedia.org/wiki/MurmurHash
+  // https://sites.google.com/site/murmurhash/
+  static const unsigned int n = 0x5bd1e995;
+  static const int r = 24;
+
+  int len = (int) hv_strlen(s);
+  hv_uint32_t x = (hv_uint32_t) (len); // seed (0) ^ len
+
+  while (len >= 4) {
+    hv_uint32_t k = *((hv_uint32_t *)s);
+    k *= n;
+    k ^= k >> r;
+    k *= n;
+    x *= n;
+    x ^= k;
+    s += 4; len -= 4;
+  }
+
+  switch(len) {
+    case 3: x ^= s[2] << 16;
+    case 2: x ^= s[1] << 8;
+    case 1: x ^= s[0]; x *= n;
+    default: break;
+  }
+
+  x ^= x >> 13;
+  x *= n;
+  x ^= x >> 15;
+
+  return x;
+}
+
+hv_uint32_t msg_getHash(const HvMessage *const m, int i) {
+  hv_assert(i < msg_getNumElements(m)); // invalid index
+  switch (msg_getType(m,i)) {
+    case BANG: return 0xFFFFFFFF;
+    case FLOAT: {
+      float f = msg_getFloat(m,i);
+      return *((hv_uint32_t *) &f);
+    }
+    case SYMBOL: return msg_symbolToHash(msg_getSymbol(m,i));
+    case HASH: return (&(m->elem)+i)->data.h;
+    default: return 0;
+  }
+}
+
+char *msg_toString(const HvMessage *m) {
+  hv_assert(msg_getNumElements(m) > 0);
+  int *len = (int *) hv_alloca(msg_getNumElements(m)*sizeof(int));
+  int size = 0; // the total length of our final buffer
+
+  // loop through every element in our list of atoms
+  // first loop figures out how long our buffer should be
+  for (int i = 0; i < msg_getNumElements(m); i++) {
+    // length of our string is each atom plus a space, or \0 on the end
+    switch (msg_getType(m, i)) {
+      case BANG: len[i] = hv_snprintf(NULL, 0, "%s", "bang") + 1; break;
+      case FLOAT: len[i] = hv_snprintf(NULL, 0, "%g", msg_getFloat(m, i)) + 1; break;
+      case SYMBOL: len[i] = hv_snprintf(NULL, 0, "%s", msg_getSymbol(m, i)) + 1; break;
+      case HASH: len[i] = hv_snprintf(NULL, 0, "0x%X", msg_getHash(m, i)) + 1; break;
+      default: break;
+    }
+    size += len[i];
+  }
+
+  hv_assert(size > 0);
+
+  // now we do the piecewise concatenation into our final string
+  // the final buffer we will pass back after concatenating all strings - user should free it
+  char *finalString = (char *) hv_malloc(size*sizeof(char));
+  int pos = 0;
+  for (int i = 0; i < msg_getNumElements(m); i++) {
+    // put a string representation of each atom into the final string
+    switch (msg_getType(m, i)) {
+      case BANG: hv_snprintf(finalString+pos, len[i], "%s", "bang"); break;
+      case FLOAT: hv_snprintf(finalString+pos, len[i], "%g", msg_getFloat(m, i)); break;
+      case SYMBOL: hv_snprintf(finalString+pos, len[i], "%s", msg_getSymbol(m, i)); break;
+      case HASH: hv_snprintf(finalString+pos, len[i], "0x%X", msg_getHash(m, i)); break;
+      default: break;
+    }
+    pos += len[i];
+    finalString[pos-1] = 32; // ASCII space
+  }
+  finalString[size-1] = '\0'; // ensure that the string is null terminated
+  return finalString;
+}
+
+/*
+ * TODO(mhroth): unnecessary for now
+bool msg_resolveDollarArguments(HvMessage *m, HvMessage *n, int z, char *buf, hv_size_t len, const char *args, ...) {
+  va_list ap;
+  va_start(ap, args);
+
+  hv_memset(buf, 0, len); // clear the buffer
+  hv_size_t j = 0; // position in buffer
+  const hv_size_t numArgs = hv_strlen(args); // the number of arguments
+
+  // if there is only one argument then the result has the chance of being a number, otherwise no
+  bool isNumber = (numArgs == 1);
+
+  for (hv_size_t i = 0; i < numArgs; ++i) {
+    switch (args[i]) {
+      case 'i': { // a message index
+        const int index = (int) va_arg(ap, int);
+        if (index < 0) {
+          // $0 always resolve to "0"
+          const hv_size_t x = 1;
+          if (x < len-j) { // always < in order to allow for trailing \0
+            j += snprintf(buf+j, len-j, "0");
+          }
+        } else {
+          switch (msg_getType(m, index)) {
+            default:
+            case BANG: break; // this case should never happen
+            case FLOAT: {
+              const hv_size_t x = snprintf(NULL, 0, "%g", msg_getFloat(m,index));
+              if (x < len-j) { // ensure that the buffer is big enough
+                j += snprintf(buf+j, len-j, "%g", msg_getFloat(m,index));
+              }
+              break;
+            }
+            case SYMBOL: {
+              const hv_size_t x = snprintf(NULL, 0, "%s", msg_getSymbol(m,index));
+              if (x < len-j) {
+                j += snprintf(buf+j, len-j, "%s", msg_getSymbol(m,index));
+                isNumber = false;
+              }
+              break;
+            }
+          }
+        }
+        break;
+      }
+      case 's': { // a string
+        const char *s = (char *) va_arg(ap, char *);
+        const hv_size_t x = snprintf(NULL, 0, "%s", s);
+        if (x <= len-j) {
+          j += snprintf(buf+j, len-j, "%s", s);
+          isNumber = false;
+        }
+        break;
+      }
+      default: break;
+    }
+  }
+
+  if (isNumber) {
+    msg_setFloat(n,z,(float) atof(buf));
+  } else {
+    msg_setSymbol(n,z,buf);
+  }
+
+  va_end(ap);
+
+  return !isNumber;
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HvMessage.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_MESSAGE_H_
+#define _HEAVY_MESSAGE_H_
+
+#include "Utils.h"
+
+typedef enum ElementType {
+  BANG,
+  FLOAT,
+  SYMBOL,
+  HASH
+} ElementType;
+
+typedef struct Element {
+  ElementType type;
+  union {
+    float f; // float
+    char *s; // symbol
+    hv_uint32_t h; // hash
+  } data;
+} Element;
+
+typedef struct HvMessage {
+  hv_uint32_t timestamp; // the sample at which this message should be processed
+  hv_uint16_t numElements;
+  hv_uint16_t numBytes; // the number of bytes that this message occupies in memory
+  Element elem;
+} HvMessage;
+
+#define HV_MESSAGE_ON_STACK(_x) (HvMessage *) hv_alloca(msg_getByteSize(_x))
+
+/** Returns the total length in bytes of this message for a given number of elements. */
+static inline hv_size_t msg_getByteSize(hv_size_t numElements) {
+  hv_assert(numElements > 0);
+  return sizeof(HvMessage) + ((numElements-1) * sizeof(Element));
+}
+
+HvMessage *msg_copy(const HvMessage *m);
+
+/** Returns the number of bytes that this message would occupy on the heap. */
+hv_size_t msg_getNumHeapBytes(const HvMessage *m);
+
+/** Copies the message into the given buffer. The buffer must be at least as large as msg_getNumHeapBytes(). */
+void msg_copyToBuffer(const HvMessage *m, char *buffer, hv_size_t len);
+
+void msg_setElementToFrom(HvMessage *n, int indexN, const HvMessage *const m, int indexM);
+
+/** Frees a message on the heap. Does nothing if argument is NULL. */
+void msg_free(HvMessage *m);
+
+HvMessage *msg_init(HvMessage *m, hv_size_t numElements, hv_uint32_t timestamp);
+
+HvMessage *msg_initWithFloat(HvMessage *m, hv_uint32_t timestamp, float f);
+
+HvMessage *msg_initWithBang(HvMessage *m, hv_uint32_t timestamp);
+
+HvMessage *msg_initWithSymbol(HvMessage *m, hv_uint32_t timestamp, char *s);
+
+HvMessage *msg_initWithHash(HvMessage *m, hv_uint32_t timestamp, hv_uint32_t h);
+
+HvMessage *msg_initV(HvMessage *const m, const hv_uint32_t timestamp, const char *format, ...);
+
+static inline hv_uint32_t msg_getTimestamp(const HvMessage *m) {
+  return m->timestamp;
+}
+
+static inline void msg_setTimestamp(HvMessage *m, hv_uint32_t timestamp) {
+  m->timestamp = timestamp;
+}
+
+static inline int msg_getNumElements(const HvMessage *m) {
+  return (int) m->numElements;
+}
+
+/** Returns the number of bytes this message in memory. */
+static inline hv_size_t msg_getNumBytes(const HvMessage *m) {
+  return m->numBytes;
+}
+
+static inline ElementType msg_getType(const HvMessage *m, int index) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  return (&(m->elem)+index)->type;
+}
+
+static inline void msg_setBang(HvMessage *m, int index) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  (&(m->elem)+index)->type = BANG;
+  (&(m->elem)+index)->data.s = NULL;
+}
+
+static inline bool msg_isBang(const HvMessage *m, int index) {
+  return (index < msg_getNumElements(m)) ? (msg_getType(m,index) == BANG) : false;
+}
+
+static inline void msg_setFloat(HvMessage *m, int index, float f) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  (&(m->elem)+index)->type = FLOAT;
+  (&(m->elem)+index)->data.f = f;
+}
+
+static inline float msg_getFloat(const HvMessage *const m, int index) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  return (&(m->elem)+index)->data.f;
+}
+
+static inline bool msg_isFloat(const HvMessage *const m, int index) {
+  return (index < msg_getNumElements(m)) ? (msg_getType(m,index) == FLOAT) : false;
+}
+
+static inline void msg_setHash(HvMessage *m, int index, hv_uint32_t h) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  (&(m->elem)+index)->type = HASH;
+  (&(m->elem)+index)->data.h = h;
+}
+
+static inline bool msg_isHash(const HvMessage *m, int index) {
+  return (index < msg_getNumElements(m)) ? (msg_getType(m, index) == HASH) : false;
+}
+
+/** Returns true if the element is a hash or symbol. False otherwise. */
+static inline bool msg_isHashLike(const HvMessage *m, int index) {
+  return (index < msg_getNumElements(m)) ? ((msg_getType(m, index) == HASH) || (msg_getType(m, index) == SYMBOL)) : false;
+}
+
+/** Returns a 32-bit hash of the given string. */
+hv_uint32_t msg_symbolToHash(const char *s);
+
+/** Returns a 32-bit hash of the given element. */
+hv_uint32_t msg_getHash(const HvMessage *const m, int i);
+
+static inline void msg_setSymbol(HvMessage *m, int index, char *s) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  (&(m->elem)+index)->type = SYMBOL;
+  (&(m->elem)+index)->data.s = s;
+}
+
+static inline char *msg_getSymbol(const HvMessage *m, int index) {
+  hv_assert(index < msg_getNumElements(m)); // invalid index
+  return (&(m->elem)+index)->data.s;
+}
+
+static inline bool msg_isSymbol(const HvMessage *m, int index) {
+  return (index < msg_getNumElements(m)) ? (msg_getType(m, index) == SYMBOL) : false;
+}
+
+bool msg_compareSymbol(const HvMessage *m, int i, const char *s);
+
+/** Returns 1 if the element i_m of message m is equal to element i_n of message n. */
+bool msg_equalsElement(const HvMessage *m, int i_m, const HvMessage *n, int i_n);
+
+bool msg_hasFormat(const HvMessage *m, const char *fmt);
+
+/**
+ * Create a string representation of the message. Suitable for use by the print object.
+ * The resulting string must be freed by the caller.
+ */
+char *msg_toString(const HvMessage *msg);
+
+/**
+ * Resolves any number of dollar arguments and generates a string based on the arguments.
+ * @param m  The message from which to take values
+ * @param n  The message to fill in
+ * @param z  The element index to resolve
+ * @param buf  The scratch (i.e. resolution) buffer
+ * @param len  The length of the scratch buffer
+ * @param args  A string of 'i' and 's' chars indicating the type of the arguments, either indicies or strings
+ * @param varargs  The components to resolve, either dollar indicies or strings.
+ * If the index is negative, the graph id is used
+ * @return  true if the resolution buffer is needed, false otherwise.
+ */
+// bool msg_resolveDollarArguments(HvMessage *m, HvMessage *n, int z, char *buf, hv_size_t len, const char *args, ...);
+
+#endif // _HEAVY_MESSAGE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HvTable.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "HvTable.h"
+
+hv_size_t hTable_init(HvTable *o, int length) {
+  o->length = length;
+  // true size of the table is always an integer multple of HV_N_SIMD
+  o->size = (length + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
+  // add an extra length for mirroring
+  o->allocated = o->size + HV_N_SIMD;
+  o->head = 0;
+  hv_size_t numBytes = o->allocated * sizeof(float);
+  o->buffer = (float *) hv_malloc(numBytes);
+  hv_memset(o->buffer, numBytes);
+  return numBytes;
+}
+
+hv_size_t hTable_initWithData(HvTable *o, int length, const float *const data) {
+  o->length = length;
+  o->size = (length + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
+  o->allocated = o->size + HV_N_SIMD;
+  o->head = 0;
+  hv_size_t numBytes = o->size * sizeof(float);
+  o->buffer = (float *) hv_malloc(numBytes);
+  hv_memset(o->buffer, numBytes);
+  hv_memcpy(o->buffer, data, length*sizeof(float));
+  return numBytes;
+}
+
+hv_size_t hTable_initWithFinalData(HvTable *o, int length, float *data) {
+  o->length = length;
+  o->size = length;
+  o->allocated = length;
+  o->buffer = data;
+  o->head = 0;
+  return 0;
+}
+
+void hTable_free(HvTable *o) {
+  hv_free(o->buffer);
+}
+
+int hTable_resize(HvTable *o, hv_uint32_t newLength) {
+  // TODO(mhroth): update context with memory allocated by table
+  // NOTE(mhroth): mirrored bytes are not necessarily carried over
+  const hv_uint32_t oldBytes = (hv_uint32_t) (o->size * sizeof(float));
+  const hv_uint32_t newSize = (newLength + HV_N_SIMD_MASK) & ~HV_N_SIMD_MASK;
+  const hv_uint32_t newAllocated = newSize + HV_N_SIMD;
+  const hv_uint32_t newBytes = (hv_uint32_t) (newAllocated * sizeof(float));
+  float *b = (float *) hv_realloc(o->buffer, newBytes);
+  hv_assert(b != NULL); // error while reallocing!
+  if (newSize > o->size) hv_clear_buffer(b+o->size, newAllocated-o->size); // clear new parts of the buffer
+  if (b != o->buffer) {
+    // the buffer has been reallocated, ensure that it is on a 32-byte boundary
+    if ((((uintptr_t) (const void *) b) & 0x10) == 0) {
+      o->buffer = b;
+    } else {
+      float *c = (float *) hv_malloc(newBytes);
+      hv_assert(c != NULL);
+      hv_clear_buffer(c, newLength);
+      const hv_size_t min = hv_min_ui(o->size, newLength);
+      hv_memcpy(c, b, min * sizeof(float));
+      hv_free(b);
+      o->buffer = c;
+    }
+  }
+  o->length = newLength;
+  o->size = newSize;
+  o->allocated = newAllocated;
+  return (int) (newBytes - oldBytes);
+}
+
+void hTable_onMessage(HvBase *_c, HvTable *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const)) {
+  if (msg_compareSymbol(m,0,"resize") && msg_isFloat(m,1) && msg_getFloat(m,1) >= 0.0f) {
+    hTable_resize(o, (int) hv_ceil_f(msg_getFloat(m,1))); // apply ceil to ensure that tables always have enough space
+
+    // send out the new size of the table
+    HvMessage *n = HV_MESSAGE_ON_STACK(1);
+    msg_initWithFloat(n, msg_getTimestamp(m), (float) hTable_getSize(o));
+    sendMessage(_c, 0, n);
+  }
+
+  else if (msg_compareSymbol(m,0,"mirror")) {
+    hv_memcpy(o->buffer+o->size, o->buffer, HV_N_SIMD*sizeof(float));
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/HvTable.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_TABLE_H_
+#define _HEAVY_TABLE_H_
+
+#include "HvBase.h"
+#include "HvMessage.h"
+#include "Utils.h"
+
+typedef struct HvTable {
+  float *buffer;
+  // the number of values that the table is requested to have
+  hv_uint32_t length;
+
+  // the number of usable values that the table actually has
+  // this is always an even multiple of HV_N_SIMD
+  hv_uint32_t size;
+
+  // Note that the true size of the table is (size + HV_N_SIMD),
+  // with the trailing values used by the system, e.g. to create a circular
+  // buffer
+  hv_uint32_t allocated;
+
+  hv_uint32_t head; // the most recently written point
+} HvTable;
+
+hv_size_t hTable_init(HvTable *o, int length);
+
+hv_size_t hTable_initWithData(HvTable *o, int length, const float *const data);
+
+hv_size_t hTable_initWithFinalData(HvTable *o, int length, float *data);
+
+void hTable_free(HvTable *o);
+
+int hTable_resize(HvTable *o, hv_uint32_t newLength);
+
+void hTable_onMessage(HvBase *_c, HvTable *o, int letIn, const HvMessage *const m,
+    void (*sendMessage)(HvBase *, int, const HvMessage *const));
+
+static inline float *hTable_getBuffer(HvTable *o) {
+  return o->buffer;
+}
+
+// the user-requested length of the table (number of floats)
+static inline hv_uint32_t hTable_getLength(HvTable *o) {
+  return o->length;
+}
+
+// the usable length of the table (an even multiple of HV_N_SIMD)
+static inline hv_uint32_t hTable_getSize(HvTable *o) {
+  return o->size;
+}
+
+// the number of floats allocated to this table (usually size + HV_N_SIMD)
+static inline hv_uint32_t hTable_getAllocated(HvTable *o) {
+  return o->allocated;
+}
+
+static inline hv_uint32_t hTable_getHead(HvTable *o) {
+  return o->head;
+}
+
+static inline void hTable_setHead(HvTable *o, hv_uint32_t head) {
+  o->head = head;
+}
+
+#endif // _HEAVY_TABLE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/MessagePool.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,141 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "MessagePool.h"
+#include "HvMessage.h"
+#include "Utils.h"
+
+// the number of bytes reserved at a time from the pool
+#define MP_BLOCK_SIZE_BYTES 512
+
+#if HV_APPLE
+#pragma mark - MessageList
+#endif
+
+typedef struct MessageListNode {
+  char *p;
+  struct MessageListNode *next;
+} MessageListNode;
+
+static inline bool ml_hasAvailable(MessagePoolList *ml) {
+  return (ml->head != NULL);
+}
+
+static char *ml_pop(MessagePoolList *ml) {
+  MessageListNode *n = ml->head;
+  ml->head = n->next;
+  n->next = ml->pool;
+  ml->pool = n;
+  char *const p = n->p;
+  n->p = NULL; // set to NULL to make it clear that this node does not have a valid buffer
+  return p;
+}
+
+/** Push a MessageListNode with the given pointer onto the head of the queue. */
+static void ml_push(MessagePoolList *ml, void *p) {
+  MessageListNode *n = NULL;
+  if (ml->pool != NULL) {
+    // take an empty MessageListNode from the pool
+    n = ml->pool;
+    ml->pool = n->next;
+  } else {
+    // a MessageListNode is not available, allocate one
+    n = (MessageListNode *) hv_malloc(sizeof(MessageListNode));
+  }
+  n->p = (char *) p;
+  n->next = ml->head;
+  ml->head = n; // push to the front of the queue
+}
+
+static void ml_free(MessagePoolList *ml) {
+  if (ml != NULL) {
+    while (ml_hasAvailable(ml)) {
+      ml_pop(ml);
+    }
+    while (ml->pool != NULL) {
+      MessageListNode *n = ml->pool;
+      ml->pool = n->next;
+      hv_free(n);
+    }
+  }
+}
+
+#if HV_APPLE
+#pragma mark - MessagePool
+#endif
+
+static hv_size_t mp_messagelistIndexForSize(hv_size_t byteSize) {
+  return (hv_size_t) hv_max_i((hv_min_max_log2((hv_uint32_t) byteSize) - 5), 0);
+}
+
+hv_size_t mp_init(MessagePool *mp, hv_size_t numKB) {
+  mp->bufferSize = numKB * 1024;
+  mp->buffer = (char *) hv_malloc(mp->bufferSize);
+  mp->bufferIndex = 0;
+
+  // initialise all message lists
+  for (int i = 0; i < MP_NUM_MESSAGE_LISTS; i++) {
+    mp->lists[i].head = NULL;
+    mp->lists[i].pool = NULL;
+  }
+
+  return mp->bufferSize;
+}
+
+void mp_free(MessagePool *mp) {
+  hv_free(mp->buffer);
+  for (int i = 0; i < MP_NUM_MESSAGE_LISTS; i++) {
+    ml_free(&mp->lists[i]);
+  }
+}
+
+void mp_freeMessage(MessagePool *mp, HvMessage *m) {
+  const hv_size_t b = msg_getNumBytes(m); // the number of bytes that a message occupies in memory
+  const hv_size_t i = mp_messagelistIndexForSize(b); // the MessagePoolList index in the pool
+  MessagePoolList *ml = &mp->lists[i];
+  const hv_size_t chunkSize = 32 << i;
+  hv_memset(m, chunkSize); // clear the chunk, just in case
+  ml_push(ml, m);
+}
+
+HvMessage *mp_addMessage(MessagePool *mp, const HvMessage *m) {
+  const hv_size_t b = msg_getNumHeapBytes(m);
+  // determine the message list index to allocate data from based on the msg size
+  // smallest chunk size is 32 bytes
+  const hv_size_t i = mp_messagelistIndexForSize(b);
+
+  assert(i < MP_NUM_MESSAGE_LISTS); // how many chunk sizes do we want to support? 32, 64, 128, 256 at the moment
+  MessagePoolList *ml = &mp->lists[i];
+  const hv_size_t chunkSize = 32 << i;
+
+  if (ml_hasAvailable(ml)) {
+    char *buf = ml_pop(ml);
+    msg_copyToBuffer(m, buf, chunkSize);
+    return (HvMessage *) buf;
+  } else {
+    // if no appropriately sized buffer is immediately available, increase the size of the used buffer
+    const hv_size_t newIndex = mp->bufferIndex + MP_BLOCK_SIZE_BYTES;
+    hv_assert(newIndex <= mp->bufferSize); // have we have exceeded the buffer size?
+
+    for (hv_size_t i = mp->bufferIndex; i < newIndex; i += chunkSize) {
+      ml_push(ml, mp->buffer + i); // push new nodes onto the list with chunk pointers
+    }
+    mp->bufferIndex = newIndex;
+    char *buf = ml_pop(ml);
+    msg_copyToBuffer(m, buf, chunkSize);
+    return (HvMessage *) buf;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/MessagePool.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MESSAGE_POOL_H_
+#define _MESSAGE_POOL_H_
+
+#include "Utils.h"
+
+struct HvMessage;
+
+#define MP_NUM_MESSAGE_LISTS 4
+
+typedef struct MessagePoolList {
+  struct MessageListNode *head; // list of currently available blocks
+  struct MessageListNode *pool; // list of currently used blocks
+} MessagePoolList;
+
+typedef struct MessagePool {
+  char *buffer; // the buffer of all messages
+  hv_size_t bufferSize; // in bytes
+  hv_size_t bufferIndex; // the number of total reserved bytes
+
+  MessagePoolList lists[MP_NUM_MESSAGE_LISTS];
+} MessagePool;
+
+/**
+ * The MessagePool is a basic memory management system. It reserves a large block of memory at initialisation
+ * and proceeds to divide this block into smaller chunks (usually 512 bytes) as they are needed. These chunks are
+ * further divided into 32, 64, 128, or 256 sections. Each of these sections is managed by a MessagePoolList (MPL).
+ * An MPL is a linked-list data structure which is initialised such that its own pool of listnodes is filled with nodes
+ * that point at each subblock (e.g. each 32-byte block of a 512-block chunk).
+ *
+ * MessagePool is loosely inspired by TCMalloc. http://goog-perftools.sourceforge.net/doc/tcmalloc.html
+ */
+
+hv_size_t mp_init(struct MessagePool *mp, hv_size_t numKB);
+
+void mp_free(struct MessagePool *mp);
+
+/**
+ * Adds a message to the pool and returns a pointer to the copy. Returns NULL
+ * if no space was available in the pool.
+ */
+struct HvMessage *mp_addMessage(struct MessagePool *mp, const struct HvMessage *m);
+
+void mp_freeMessage(struct MessagePool *mp, struct HvMessage *m);
+
+#endif // _MESSAGE_POOL_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/MessageQueue.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,218 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "MessageQueue.h"
+#include "Utils.h"
+
+hv_size_t mq_init(MessageQueue *q) {
+  q->head = NULL;
+  q->tail = NULL;
+  q->pool = NULL;
+  return mp_init(&q->mp, 1);
+}
+
+void mq_initWithPoolSize(MessageQueue *q, hv_size_t poolSizeKB) {
+  q->head = NULL;
+  q->tail = NULL;
+  q->pool = NULL;
+  mp_init(&q->mp, poolSizeKB);
+}
+
+void mq_free(MessageQueue *q) {
+  mq_clear(q);
+  while (q->pool != NULL) {
+    MessageNode *n = q->pool;
+    q->pool = q->pool->next;
+    hv_free(n);
+  }
+  mp_free(&q->mp);
+}
+
+static MessageNode *mq_getOrCreateNodeFromPool(MessageQueue *q) {
+  if (q->pool == NULL) {
+    // if necessary, create a new empty node
+    q->pool = (MessageNode *) hv_malloc(sizeof(MessageNode));
+    q->pool->next = NULL;
+  }
+  MessageNode *node = q->pool;
+  q->pool = q->pool->next;
+  return node;
+}
+
+int mq_size(MessageQueue *q) {
+    int size = 0;
+    MessageNode *n = q->head;
+    while (n != NULL) {
+        ++size;
+        n = n->next;
+    }
+    return size;
+}
+
+HvMessage *mq_addMessage(MessageQueue *q, const HvMessage *m, int let,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *)) {
+  MessageNode *node = mq_getOrCreateNodeFromPool(q);
+  node->m = mp_addMessage(&q->mp, m);
+  node->let = let;
+  node->sendMessage = sendMessage;
+  node->prev = NULL;
+  node->next = NULL;
+
+  if (q->tail != NULL) {
+    // the list already contains elements
+    q->tail->next = node;
+    node->prev = q->tail;
+    q->tail = node;
+  } else {
+    // the list is empty
+    node->prev = NULL;
+    q->head = node;
+    q->tail = node;
+  }
+  return mq_node_getMessage(node);
+}
+
+HvMessage *mq_addMessageByTimestamp(MessageQueue *q, HvMessage *m, int let,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *)) {
+  if (mq_hasMessage(q)) {
+    MessageNode *n = mq_getOrCreateNodeFromPool(q);
+    n->m = mp_addMessage(&q->mp, m);
+    n->let = let;
+    n->sendMessage = sendMessage;
+
+    if (msg_getTimestamp(m) < msg_getTimestamp(q->head->m)) {
+      // the message occurs before the current head
+      n->next = q->head;
+      q->head->prev = n;
+      n->prev = NULL;
+      q->head = n;
+    } else if (msg_getTimestamp(m) >= msg_getTimestamp(q->tail->m)) {
+      // the message occurs after the current tail
+      n->next = NULL;
+      n->prev = q->tail;
+      q->tail->next = n;
+      q->tail = n;
+    } else {
+      // the message occurs somewhere between the head and tail
+      MessageNode *node = q->head;
+      while (node != NULL) {
+        if (m->timestamp < msg_getTimestamp(node->next->m)) {
+          MessageNode *r = node->next;
+          node->next = n;
+          n->next = r;
+          n->prev = node;
+          r->prev = n;
+          break;
+        }
+        node = node->next;
+      }
+    }
+    return n->m;
+  } else {
+    // add a message to the head
+    return mq_addMessage(q, m, let, sendMessage);
+  }
+}
+
+void mq_pop(MessageQueue *q) {
+  if (mq_hasMessage(q)) {
+    MessageNode *n = q->head;
+
+    mp_freeMessage(&q->mp, n->m);
+    n->m = NULL;
+
+    n->let = 0;
+    n->sendMessage = NULL;
+
+    q->head = n->next;
+    if (q->head == NULL) {
+      q->tail = NULL;
+    } else {
+      q->head->prev = NULL;
+    }
+    n->next = q->pool;
+    n->prev = NULL;
+    q->pool = n;
+  }
+}
+
+void mq_removeMessage(MessageQueue *q, HvMessage *m, void (*sendMessage)(struct HvBase *, int, const HvMessage *)) {
+  if (mq_hasMessage(q)) {
+    if (mq_node_getMessage(q->head) == m) { // msg in head node
+      // only remove the message if sendMessage is the same as the stored one,
+      // if the sendMessage argument is NULL, it is not checked and will remove any matching message pointer
+      if (sendMessage == NULL || q->head->sendMessage == sendMessage) {
+        mq_pop(q);
+      }
+    } else {
+      MessageNode *prevNode = q->head;
+      MessageNode *currNode = q->head->next;
+      while ((currNode != NULL) && (currNode->m != m)) {
+        prevNode = currNode;
+        currNode = currNode->next;
+      }
+      if (currNode != NULL) {
+        if (sendMessage == NULL || currNode->sendMessage == sendMessage) {
+          mp_freeMessage(&q->mp, m);
+          currNode->m = NULL;
+          currNode->let = 0;
+          currNode->sendMessage = NULL;
+          if (currNode == q->tail) { // msg in tail node
+            prevNode->next = NULL;
+            q->tail = prevNode;
+          } else { // msg in middle node
+            prevNode->next = currNode->next;
+            currNode->next->prev = prevNode;
+          }
+          currNode->next = (q->pool == NULL) ? NULL : q->pool;
+          currNode->prev = NULL;
+          q->pool = currNode;
+        }
+      }
+    }
+  }
+}
+
+void mq_clear(MessageQueue *q) {
+  while (mq_hasMessage(q)) {
+    mq_pop(q);
+  }
+}
+
+void mq_clearAfter(MessageQueue *q, const double timestamp) {
+  MessageNode *n = q->tail;
+  while (n != NULL && timestamp <= msg_getTimestamp(n->m)) {
+    // free the node's message
+    mp_freeMessage(&q->mp, n->m);
+    n->m = NULL;
+    n->let = 0;
+    n->sendMessage = NULL;
+
+    // the tail points at the previous node
+    q->tail = n->prev;
+
+    // put the node back in the pool
+    n->next = q->pool;
+    n->prev = NULL;
+    if (q->pool != NULL) q->pool->prev = n;
+    q->pool = n;
+
+    // update the tail node
+    n = q->tail;
+  }
+
+  if (q->tail == NULL) q->head = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/MessageQueue.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MESSAGE_QUEUE_H_
+#define _MESSAGE_QUEUE_H_
+
+#include "HvMessage.h"
+#include "MessagePool.h"
+
+struct HvBase;
+
+typedef struct MessageNode {
+  struct MessageNode *prev; // doubly linked list
+  struct MessageNode *next;
+  HvMessage *m;
+  void (*sendMessage)(struct HvBase *, int, const HvMessage *);
+  int let;
+} MessageNode;
+
+/** A doubly linked list containing scheduled messages. */
+typedef struct MessageQueue {
+  MessageNode *head; // the head of the queue
+  MessageNode *tail; // the tail of the queue
+  MessageNode *pool; // the head of the reserve pool
+  MessagePool mp;
+} MessageQueue;
+
+hv_size_t mq_init(MessageQueue *q);
+
+void mq_initWithPoolSize(MessageQueue *q, hv_size_t poolSizeKB);
+
+void mq_free(MessageQueue *q);
+
+int mq_size(MessageQueue *q);
+
+static inline HvMessage *mq_node_getMessage(MessageNode *n) {
+  return n->m;
+}
+
+static inline int mq_node_getLet(MessageNode *n) {
+  return n->let;
+}
+
+static inline bool mq_hasMessage(MessageQueue *q) {
+  return (q->head != NULL);
+}
+
+// true if there is a message and it occurs before (<) timestamp
+static inline bool mq_hasMessageBefore(MessageQueue *const q, const hv_uint32_t timestamp) {
+  return mq_hasMessage(q) && (msg_getTimestamp(mq_node_getMessage(q->head)) < timestamp);
+}
+
+static inline MessageNode *mq_peek(MessageQueue *q) {
+  return q->head;
+}
+
+/** Appends the message to the end of the queue. */
+HvMessage *mq_addMessage(MessageQueue *q, const HvMessage *m, int let,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *));
+
+/** Insert in ascending order the message acccording to its timestamp. */
+HvMessage *mq_addMessageByTimestamp(MessageQueue *q, HvMessage *m, int let,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *));
+
+/** Pop the message at the head of the queue (and free its memory). */
+void mq_pop(MessageQueue *q);
+
+/** Remove a message from the queue (and free its memory) */
+void mq_removeMessage(MessageQueue *q, HvMessage *m,
+    void (*sendMessage)(struct HvBase *, int, const HvMessage *));
+
+/** Clears (and frees) all messages in the queue. */
+void mq_clear(MessageQueue *q);
+
+/** Removes all messages occuring at or after the given timestamp. */
+void mq_clearAfter(MessageQueue *q, const double timestamp);
+
+#endif // _MESSAGE_QUEUE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalDel1.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalDel1.h"
+
+hv_size_t sDel1_init(SignalDel1 *o) {
+#if HV_SIMD_AVX
+  o->x = _mm256_setzero_ps();
+#elif HV_SIMD_SSE
+  o->x = _mm_setzero_ps();
+#elif HV_SIMD_NEON
+  o->x = vdupq_n_f32(0.0f);
+#else
+  o->x = 0.0f;
+#endif
+  return 0;
+}
+
+void sDel1_onMessage(HvBase *_c, SignalDel1 *o, int letIn, const HvMessage *m) {
+  if (letIn == 2) {
+    if (msg_compareSymbol(m, 0, "clear")) {
+#if HV_SIMD_AVX
+      o->x = _mm256_setzero_ps();
+#elif HV_SIMD_SSE
+      o->x = _mm_setzero_ps();
+#elif HV_SIMD_NEON
+      o->x = vdupq_n_f32(0.0f);
+#else
+      o->x = 0.0f;
+#endif
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalDel1.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SIGNAL_DEL1_H_
+#define _SIGNAL_DEL1_H_
+
+#include "HvBase.h"
+
+typedef struct SignalDel1 {
+  hv_bufferf_t x;
+} SignalDel1;
+
+hv_size_t sDel1_init(SignalDel1 *o);
+
+void sDel1_onMessage(HvBase *_c, SignalDel1 *o, int letIn, const HvMessage *m);
+
+static inline void __hv_del1_f(SignalDel1 *o, hv_bInf_t bIn0, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  __m256 x = _mm256_permute_ps(bIn0, _MM_SHUFFLE(2,1,0,3)); // [3 0 1 2 7 4 5 6]
+  __m256 n = _mm256_permute2f128_ps(o->x,x,0x1);            // [h e f g 3 0 1 2]
+  *bOut = _mm256_blend_ps(x, n, 0x11);                      // [g 0 1 2 3 4 5 6]
+  o->x = x;
+#elif HV_SIMD_SSE
+  __m128 n = _mm_blend_ps(o->x, bIn0, 0x7);
+  *bOut = _mm_shuffle_ps(n, n, _MM_SHUFFLE(2,1,0,3));
+  o->x = bIn0;
+#elif HV_SIMD_NEON
+  *bOut = vextq_f32(o->x, bIn0, 3);
+  o->x = bIn0;
+#else
+  *bOut = o->x;
+  o->x = bIn0;
+#endif
+}
+
+#endif // _SIGNAL_DEL1_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalPhasor.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalPhasor.h"
+
+// input phase is in the range of [0,1]. It is independent of o->phase.
+#if HV_SIMD_AVX
+static void sPhasor_updatePhase(SignalPhasor *o, float p) {
+  o->phase = _mm256_set_ps(
+      p+1.0f+7.0f*o->step.f2sc, p+1.0f+6.0f*o->step.f2sc,
+      p+1.0f+5.0f*o->step.f2sc, p+1.0f+4.0f*o->step.f2sc,
+      p+1.0f+3.0f*o->step.f2sc, p+1.0f+2.0f*o->step.f2sc,
+      p+1.0f+o->step.f2sc,      p+1.0f);
+
+  // ensure that o->phase is still in range [1,2]
+  o->phase = _mm256_or_ps(_mm256_andnot_ps(
+      _mm256_set1_ps(-INFINITY), o->phase), _mm256_set1_ps(1.0f));
+#elif HV_SIMD_SSE
+static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) {
+  o->phase = _mm_set_epi32(3*o->step.s+p, 2*o->step.s+p, o->step.s+p, p);
+#elif HV_SIMD_NEON
+static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) {
+  o->phase = (uint32x4_t) {p, o->step.s+p, 2*o->step.s+p, 3*o->step.s+p};
+#else // HV_SIMD_NONE
+static void sPhasor_updatePhase(SignalPhasor *o, hv_uint32_t p) {
+  o->phase = p;
+#endif
+}
+
+static void sPhasor_updateFrequency(SignalPhasor *o, float f, double r) {
+#if HV_SIMD_AVX
+  o->step.f2sc = (float) (f/r);
+  o->inc = _mm256_set1_ps((float) (8.0f*f/r));
+  sPhasor_updatePhase(o, o->phase[0]);
+#elif HV_SIMD_SSE
+  o->step.s = (hv_int32_t) (f*(4294967296.0/r));
+  o->inc = _mm_set1_epi32(4*o->step.s);
+  sPhasor_updatePhase(o, (hv_uint32_t) (o->phase[0] & 0xFFFFFFFFL));
+#elif HV_SIMD_NEON
+  o->step.s = (hv_int32_t) (f*(4294967296.0/r));
+  o->inc = vdupq_n_s32(4*o->step.s);
+  sPhasor_updatePhase(o, vgetq_lane_u32(o->phase, 0));
+#else // HV_SIMD_NONE
+  o->step.s = (hv_int32_t) (f*(4294967296.0/r));
+  o->inc = o->step.s;
+  // no need to update phase
+#endif
+}
+
+hv_size_t sPhasor_init(SignalPhasor *o, double samplerate) {
+#if HV_SIMD_AVX
+  o->phase = _mm256_set1_ps(1.0f);
+  o->inc = _mm256_setzero_ps();
+  o->step.f2sc = (float) (1.0/samplerate);
+#elif HV_SIMD_SSE
+  o->phase = _mm_setzero_si128();
+  o->inc = _mm_setzero_si128();
+  o->step.f2sc = (float) (4294967296.0/samplerate);
+#elif HV_SIMD_NEON
+  o->phase = vdupq_n_u32(0);
+  o->inc = vdupq_n_s32(0);
+  o->step.f2sc = (float) (4294967296.0/samplerate);
+#else // HV_SIMD_NONE
+  o->phase = 0;
+  o->inc = 0;
+  o->step.f2sc = (float) (4294967296.0/samplerate);
+#endif
+  return 0;
+}
+
+void sPhasor_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m) {
+  if (letIn == 1) {
+    if (msg_isFloat(m,0)) {
+      float phase = msg_getFloat(m,0);
+      while (phase < 0.0f) phase += 1.0f; // wrap phase to [0,1]
+      while (phase > 1.0f) phase -= 1.0f;
+#if HV_SIMD_AVX
+      sPhasor_updatePhase(o, phase);
+#else // HV_SIMD_SSE || HV_SIMD_NEON || HV_SIMD_NONE
+      sPhasor_updatePhase(o, (hv_int32_t) (phase * 4294967296.0));
+#endif
+    }
+  }
+}
+
+hv_size_t sPhasor_k_init(SignalPhasor *o, float frequency, double samplerate) {
+  sPhasor_updateFrequency(o, frequency, samplerate);
+  sPhasor_updatePhase(o, 0);
+  return 0;
+}
+
+void sPhasor_k_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m) {
+  if (msg_isFloat(m,0)) {
+    switch (letIn) {
+      case 0: sPhasor_updateFrequency(o, msg_getFloat(m,0), ctx_getSampleRate(_c)); break;
+      case 1: {
+        float phase = msg_getFloat(m,0);
+        while (phase < 0.0f) phase += 1.0f; // wrap phase to [0,1]
+        while (phase > 1.0f) phase -= 1.0f;
+#if HV_SIMD_AVX
+        sPhasor_updatePhase(o, phase);
+#else // HV_SIMD_SSE || HV_SIMD_NEON || HV_SIMD_NONE
+        sPhasor_updatePhase(o, (hv_uint32_t) (phase * 4294967296.0));
+#endif
+        break;
+      }
+      default: break;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalPhasor.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,131 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_SIGNAL_PHASOR_H_
+#define _HEAVY_SIGNAL_PHASOR_H_
+
+#include "HvBase.h"
+
+typedef struct SignalPhasor {
+#if HV_SIMD_AVX
+  __m256 phase; // current phase
+  __m256 inc;   // phase increment
+#elif HV_SIMD_SSE
+  __m128i phase;
+  __m128i inc;
+#elif HV_SIMD_NEON
+  uint32x4_t phase;
+  int32x4_t inc;
+#else // HV_SIMD_NONE
+  hv_uint32_t phase;
+  hv_int32_t inc;
+#endif
+  union {
+    float f2sc; // float to step conversion (used for __phasor~f)
+    hv_int32_t s; // step value (used for __phasor_k~f)
+  } step;
+} SignalPhasor;
+
+hv_size_t sPhasor_init(SignalPhasor *o, double samplerate);
+
+hv_size_t sPhasor_k_init(SignalPhasor *o, float frequency, double samplerate);
+
+void sPhasor_k_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m);
+
+void sPhasor_onMessage(HvBase *_c, SignalPhasor *o, int letIn, const HvMessage *m);
+
+static inline void __hv_phasor_f(SignalPhasor *o, hv_bInf_t bIn, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  __m256 p = _mm256_mul_ps(bIn, _mm256_set1_ps(o->step.f2sc)); // a b c d e f g h
+
+  __m256 z = _mm256_setzero_ps();
+
+  // http://stackoverflow.com/questions/11906814/how-to-rotate-an-sse-avx-vector
+  __m256 a = _mm256_permute_ps(p, _MM_SHUFFLE(2,1,0,3)); // d a b c h e f g
+  __m256 b = _mm256_permute2f128_ps(a, a, 0x01);         // h e f g d a b c
+  __m256 c = _mm256_blend_ps(a, b, 0x10);                // d a b c d e f g
+  __m256 d = _mm256_blend_ps(c, z, 0x01);                // 0 a b c d e f g
+  __m256 e = _mm256_add_ps(p, d); // a (a+b) (b+c) (c+d) (d+e) (e+f) (f+g) (g+h)
+
+  __m256 f = _mm256_permute_ps(e, _MM_SHUFFLE(1,0,3,2)); // (b+c) (c+d) a (a+b) (f+g) (g+h) (d+e) (e+f)
+  __m256 g = _mm256_permute2f128_ps(f, f, 0x01);         // (f+g) (g+h) (d+e) (e+f) (b+c) (c+d) a (a+b)
+  __m256 h = _mm256_blend_ps(f, g, 0x33);                // (b+c) (c+d) a (a+b) (b+c) (c+d) (d+e) (e+f)
+  __m256 i = _mm256_blend_ps(h, z, 0x03);                // 0 0 a (a+b) (b+c) (c+d) (d+e) (e+f)
+  __m256 j = _mm256_add_ps(e, i); // a (a+b) (a+b+c) (a+b+c+d) (b+c+d+e) (c+d+e+f) (d+e+f+g) (e+f+g+h)
+
+  __m256 k = _mm256_permute2f128_ps(j, z, 0x02);         // 0 0 0 0 a (a+b) (a+b+c) (a+b+c+d) (b+c+d+e)
+  __m256 m = _mm256_add_ps(j, k); // a (a+b) (a+b+c) (a+b+c+d) (a+b+c+d+e) (a+b+c+d+e+f) (a+b+c+d+e+f+g) (a+b+c+d+e+f+g+h)
+
+  __m256 n = _mm256_or_ps(_mm256_andnot_ps(
+      _mm256_set1_ps(-INFINITY),
+      _mm256_add_ps(o->phase, m)),
+      _mm256_set1_ps(1.0f));
+
+  *bOut = _mm256_sub_ps(n, _mm256_set1_ps(1.0f));
+
+  __m256 x = _mm256_permute_ps(n, _MM_SHUFFLE(3,3,3,3));
+  o->phase = _mm256_permute2f128_ps(x, x, 0x11);
+#elif HV_SIMD_SSE
+  __m128i p = _mm_cvtps_epi32(_mm_mul_ps(bIn, _mm_set1_ps(o->step.f2sc))); // convert frequency to step
+  p = _mm_add_epi32(p, _mm_slli_si128(p, 4)); // add incremental steps to phase (prefix sum)
+  p = _mm_add_epi32(p, _mm_slli_si128(p, 8)); // http://stackoverflow.com/questions/10587598/simd-prefix-sum-on-intel-cpu?rq=1
+  p = _mm_add_epi32(o->phase, p);
+  *bOut = _mm_sub_ps(_mm_castsi128_ps(
+      _mm_or_si128(_mm_srli_epi32(p, 9),
+      (__m128i) {0x3F8000003F800000L, 0x3F8000003F800000L})),
+      _mm_set1_ps(1.0f));
+  o->phase = _mm_shuffle_epi32(p, _MM_SHUFFLE(3,3,3,3));
+#elif HV_SIMD_NEON
+  int32x4_t p = vcvtq_s32_f32(vmulq_n_f32(bIn, o->step.f2sc));
+  p = vaddq_s32(p, vextq_s32(vdupq_n_s32(0), p, 3)); // http://stackoverflow.com/questions/11259596/arm-neon-intrinsics-rotation
+  p = vaddq_s32(p, vextq_s32(vdupq_n_s32(0), p, 2));
+  uint32x4_t pp = vaddq_u32(o->phase, vreinterpretq_u32_s32(p));
+  *bOut = vsubq_f32(vreinterpretq_f32_u32(vorrq_u32(vshrq_n_u32(pp, 9), vdupq_n_u32(0x3F800000))), vdupq_n_f32(1.0f));
+  o->phase = vdupq_n_u32(pp[3]);
+#else // HV_SIMD_NONE
+  const hv_uint32_t p = (o->phase >> 9) | 0x3F800000;
+  *bOut = *((float *) (&p)) - 1.0f;
+  o->phase += ((int) (bIn * o->step.f2sc));
+#endif
+}
+
+static inline void __hv_phasor_k_f(SignalPhasor *o, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  *bOut = _mm256_sub_ps(o->phase, _mm256_set1_ps(1.0f));
+  o->phase = _mm256_or_ps(_mm256_andnot_ps(
+      _mm256_set1_ps(-INFINITY),
+      _mm256_add_ps(o->phase, o->inc)),
+      _mm256_set1_ps(1.0f));
+#elif HV_SIMD_SSE
+  *bOut = _mm_sub_ps(_mm_castsi128_ps(
+      _mm_or_si128(_mm_srli_epi32(o->phase, 9),
+      (__m128i) {0x3F8000003F800000L, 0x3F8000003F800000L})),
+      _mm_set1_ps(1.0f));
+  o->phase = _mm_add_epi32(o->phase, o->inc);
+#elif HV_SIMD_NEON
+  *bOut = vsubq_f32(vreinterpretq_f32_u32(
+      vorrq_u32(vshrq_n_u32(o->phase, 9),
+      vdupq_n_u32(0x3F800000))),
+      vdupq_n_f32(1.0f));
+  o->phase = vaddq_u32(o->phase, vreinterpretq_u32_s32(o->inc));
+#else // HV_SIMD_NONE
+  const hv_uint32_t p = (o->phase >> 9) | 0x3F800000;
+  *bOut = *((float *) (&p)) - 1.0f;
+  o->phase += o->inc;
+#endif
+}
+
+#endif // _HEAVY_SIGNAL_PHASOR_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalRPole.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalRPole.h"
+
+hv_size_t sRPole_init(SignalRPole *o) {
+#if HV_SIMD_AVX
+  sDel1_init(&o->sDel1_fxiLN);
+  sDel1_init(&o->sDel1_kjkpV);
+  sDel1_init(&o->sDel1_dkIWc);
+  sDel1_init(&o->sDel1_bVeoW);
+  sDel1_init(&o->sDel1_PulZn);
+  sDel1_init(&o->sDel1_yTFig);
+  sDel1_init(&o->sDel1_Is9Qf);
+  sDel1_init(&o->sDel1_LIyNt);
+  sDel1_init(&o->sDel1_VqpU3);
+  sDel1_init(&o->sDel1_ZVYeg);
+  sDel1_init(&o->sDel1_IVAZh);
+  sDel1_init(&o->sDel1_F8WrY);
+  sDel1_init(&o->sDel1_rkFMy);
+  sDel1_init(&o->sDel1_BeqSK);
+  __hv_zero_f(&o->ym);
+#elif HV_SIMD_SSE || HV_SIMD_NEON
+  sDel1_init(&o->sDel1_i8Twk);
+  sDel1_init(&o->sDel1_KYibU);
+  sDel1_init(&o->sDel1_spa5V);
+  sDel1_init(&o->sDel1_3HXdb);
+  sDel1_init(&o->sDel1_Aj1oK);
+  sDel1_init(&o->sDel1_jNX1g);
+  __hv_zero_f(&o->ym);
+#else
+  o->ym = 0.0f;
+#endif
+  return 0;
+}
+
+void sRPole_onMessage(HvBase *_c, SignalRPole *o, int letIn, const HvMessage *m) {
+  // TODO
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalRPole.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SIGNAL_RPOLE_H_
+#define _SIGNAL_RPOLE_H_
+
+#include "HvBase.h"
+#include "SignalDel1.h"
+#include "HeavyMath.h"
+
+// implements y[n] = x[n] - a*y[n-1]
+// H(z) = 1/(1+a*z^-1)
+typedef struct SignalRPole {
+#if HV_SIMD_AVX
+  SignalDel1 sDel1_fxiLN;
+  SignalDel1 sDel1_kjkpV;
+  SignalDel1 sDel1_dkIWc;
+  SignalDel1 sDel1_bVeoW;
+  SignalDel1 sDel1_PulZn;
+  SignalDel1 sDel1_yTFig;
+  SignalDel1 sDel1_Is9Qf;
+  SignalDel1 sDel1_LIyNt;
+  SignalDel1 sDel1_VqpU3;
+  SignalDel1 sDel1_ZVYeg;
+  SignalDel1 sDel1_IVAZh;
+  SignalDel1 sDel1_F8WrY;
+  SignalDel1 sDel1_rkFMy;
+  SignalDel1 sDel1_BeqSK;
+  hv_bufferf_t ym;
+#elif HV_SIMD_SSE || HV_SIMD_NEON
+  SignalDel1 sDel1_i8Twk;
+  SignalDel1 sDel1_KYibU;
+  SignalDel1 sDel1_spa5V;
+  SignalDel1 sDel1_3HXdb;
+  SignalDel1 sDel1_Aj1oK;
+  SignalDel1 sDel1_jNX1g;
+  hv_bufferf_t ym;
+#else
+  hv_bufferf_t ym;
+#endif
+} SignalRPole;
+
+hv_size_t sRPole_init(SignalRPole *o);
+
+void sRPole_onMessage(HvBase *_c, SignalRPole *o, int letIn, const HvMessage *m);
+
+static inline void __hv_rpole_f(SignalRPole *o, hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+  hv_bufferf_t a, b, c, d, e, f, g, i, j, k, l, m, n;
+  __hv_del1_f(&o->sDel1_fxiLN, bIn1, &a);
+  __hv_mul_f(bIn1, a, &b);
+  __hv_del1_f(&o->sDel1_kjkpV, a, &a);
+  __hv_mul_f(b, a, &c);
+  __hv_del1_f(&o->sDel1_dkIWc, a, &a);
+  __hv_mul_f(c, a, &d);
+  __hv_del1_f(&o->sDel1_bVeoW, a, &a);
+  __hv_mul_f(d, a, &e);
+  __hv_del1_f(&o->sDel1_PulZn, a, &a);
+  __hv_mul_f(e, a, &f);
+  __hv_del1_f(&o->sDel1_yTFig, a, &a);
+  __hv_mul_f(f, a, &g);
+  __hv_del1_f(&o->sDel1_Is9Qf, a, &a);
+  __hv_mul_f(g, a, &a);
+  __hv_del1_f(&o->sDel1_LIyNt, bIn0, &i);
+  __hv_del1_f(&o->sDel1_VqpU3, i, &j);
+  __hv_del1_f(&o->sDel1_ZVYeg, j, &k);
+  __hv_del1_f(&o->sDel1_IVAZh, k, &l);
+  __hv_del1_f(&o->sDel1_F8WrY, l, &m);
+  __hv_del1_f(&o->sDel1_rkFMy, m, &n);
+  __hv_mul_f(i, bIn1, &i);
+  __hv_sub_f(bIn0, i, &i);
+  __hv_fma_f(j, b, i, &i);
+  __hv_mul_f(k, c, &c);
+  __hv_sub_f(i, c, &c);
+  __hv_fma_f(l, d, c, &c);
+  __hv_mul_f(m, e, &e);
+  __hv_sub_f(c, e, &e);
+  __hv_fma_f(n, f, e, &e);
+  __hv_del1_f(&o->sDel1_BeqSK, n, &n);
+  __hv_mul_f(n, g, &g);
+  __hv_sub_f(e, g, &g);
+  __hv_fma_f(a, o->ym, g, &g);
+  o->ym = g;
+  *bOut = g;
+#elif HV_SIMD_SSE || HV_SIMD_NEON
+  hv_bufferf_t a, b, c, e, f;
+  __hv_del1_f(&o->sDel1_i8Twk, bIn1, &a);
+  __hv_mul_f(bIn1, a, &b);
+  __hv_del1_f(&o->sDel1_KYibU, a, &a);
+  __hv_mul_f(b, a, &c);
+  __hv_del1_f(&o->sDel1_spa5V, a, &a);
+  __hv_mul_f(c, a, &a);
+  __hv_del1_f(&o->sDel1_3HXdb, bIn0, &e);
+  __hv_del1_f(&o->sDel1_Aj1oK, e, &f);
+  __hv_mul_f(e, bIn1, &e);
+  __hv_sub_f(bIn0, e, &e);
+  __hv_fma_f(f, b, e, &e);
+  __hv_del1_f(&o->sDel1_jNX1g, f, &f);
+  __hv_mul_f(f, c, &c);
+  __hv_sub_f(e, c, &c);
+  __hv_fma_f(a, o->ym, c, &c);
+  o->ym = c;
+  *bOut = c;
+#else
+  *bOut = bIn0 - bIn1 * o->ym;
+  o->ym = *bOut;
+#endif
+}
+
+#endif // _SIGNAL_RPOLE_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalSamphold.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalSamphold.h"
+
+hv_size_t sSamphold_init(SignalSamphold *o) {
+#if HV_SIMD_AVX
+  o->s = _mm256_setzero_ps();
+#elif HV_SIMD_SSE
+  o->s = _mm_setzero_ps();
+#elif HV_SIMD_NEON
+  o->s = vdupq_n_f32(0.0f);
+#else
+  o->s = 0.0f;
+#endif
+  return 0;
+}
+
+void sSamphold_onMessage(HvBase *_c, SignalSamphold *o, int letIndex,
+    const HvMessage *const m, void *sendMessage) {
+  switch (letIndex) {
+    case 2: {
+      if (msg_isFloat(m,0)) {
+#if HV_SIMD_AVX
+        o->s = _mm256_set1_ps(msg_getFloat(m,0));
+#elif HV_SIMD_SSE
+        o->s = _mm_set1_ps(msg_getFloat(m,0));
+#elif HV_SIMD_NEON
+        o->s = vdupq_n_f32(msg_getFloat(m,0));
+#else
+        o->s = msg_getFloat(m,0);
+#endif
+      }
+      break;
+    }
+    default: break;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalSamphold.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,248 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SIGNAL_SAMPHOLD_H_
+#define _SIGNAL_SAMPHOLD_H_
+
+#include "HvBase.h"
+
+typedef struct SignalSamphold {
+  hv_bufferf_t s;
+} SignalSamphold;
+
+hv_size_t sSamphold_init(SignalSamphold *o);
+
+static inline void __hv_samphold_f(SignalSamphold *o, hv_bInf_t bIn0, hv_bInf_t bIn1, hv_bOutf_t bOut) {
+#if HV_SIMD_AVX
+#warning __hv_samphold_f() not implemented
+#elif HV_SIMD_SSE
+  switch (_mm_movemask_ps(bIn1)) {
+    default:
+    case 0x0: *bOut = o->s; break;
+    case 0x1: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(0,0,0,0));
+      o->s = *bOut;
+      break;
+    }
+    case 0x2: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(1,1,1,1));
+      *bOut = _mm_blend_ps(o->s, x, 0xE);
+      o->s = x;
+      break;
+    }
+    case 0x3: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(1,1,1,1));
+      *bOut = _mm_blend_ps(bIn0, x, 0xC);
+      o->s = x;
+      break;
+    }
+    case 0x4: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2));
+      *bOut = _mm_blend_ps(o->s, x, 0xC);
+      o->s = x;
+      break;
+    }
+    case 0x5: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,0,0));
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2));
+      break;
+    }
+    case 0x6: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,1,0));
+      *bOut = _mm_blend_ps(o->s, x, 0xE);
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2));
+      break;
+    }
+    case 0x7: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(2,2,2,2));
+      *bOut = _mm_blend_ps(bIn0, x, 0x8);
+      o->s = x;
+      break;
+    }
+    case 0x8: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      *bOut = _mm_blend_ps(o->s, x, 0x8);
+      o->s = x;
+      break;
+    }
+    case 0x9: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,0,0,0));
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xA: {
+      const __m128 x = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,1,1,0));
+      *bOut = _mm_blend_ps(o->s, x, 0xE);
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xB: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,1,1,0));
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xC: {
+      *bOut = _mm_blend_ps(o->s, bIn0, 0xC);
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xD: {
+      *bOut = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,2,0,0));
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xE: {
+      *bOut = _mm_blend_ps(o->s, bIn0, 0xE);
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+    case 0xF: {
+      *bOut = bIn0;
+      o->s = _mm_shuffle_ps(bIn0, bIn0, _MM_SHUFFLE(3,3,3,3));
+      break;
+    }
+  }
+#elif HV_SIMD_NEON
+  uint32x4_t mmA = vandq_u32(
+      vreinterpretq_u32_f32(bIn1), (uint32x4_t) {0x1, 0x2, 0x4, 0x8}); // [0 1 2 3]
+  uint32x4_t mmB = vextq_u32(mmA, mmA, 2);                             // [2 3 0 1]
+  uint32x4_t mmC = vorrq_u32(mmA, mmB);                                // [0+2 1+3 0+2 1+3]
+  uint32x4_t mmD = vextq_u32(mmC, mmC, 3);                             // [1+3 0+2 1+3 0+2]
+  uint32x4_t mmE = vorrq_u32(mmC, mmD);                                // [0+1+2+3 ...]
+  uint32_t movemask = vgetq_lane_u32(mmE, 0);
+  switch (movemask) {
+    default:
+    case 0x0: *bOut = o->s; break;
+    case 0x1: {
+      *bOut = vdupq_n_f32(vgetq_lane_f32(bIn0,0));
+      o->s = *bOut;
+      break;
+    }
+    case 0x2: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1));
+      *bOut = vextq_f32(o->s, x, 3);
+      o->s = x;
+      break;
+    }
+    case 0x3: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {~0x0, 0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, ~0x0, ~0x0, ~0x0})));
+      o->s = x;
+      break;
+    }
+    case 0x4: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,2));
+      *bOut = vextq_f32(o->s, x, 2);
+      o->s = x;
+      break;
+    }
+    case 0x5: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0));
+      const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,2));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {~0x0, ~0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, ~0x0, ~0x0})));
+      o->s = y;
+    }
+    case 0x6: {
+      const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      float32x4_t z = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {~0x0, 0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, ~0x0, ~0x0, 0x0})));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(z), (uint32x4_t) {~0x0, ~0x0, ~0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, 0x0, ~0x0})));
+      o->s = y;
+    }
+    case 0x7: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,2));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {~0x0, ~0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0x0, ~0x0, ~0x0})));
+      o->s = x;
+      break;
+    }
+    case 0x8: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      *bOut = vextq_f32(o->s, x, 1);
+      o->s = x;
+      break;
+    }
+    case 0x9: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {~0x0, ~0x0, ~0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, 0x0, 0x0, ~0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+    }
+    case 0xA: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1));
+      const float32x4_t y = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      float32x4_t z = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {~0x0, 0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, ~0x0, ~0x0, 0x0})));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(z), (uint32x4_t) {~0x0, ~0x0, ~0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(y), (uint32x4_t) {0x0, 0x0, 0x0, ~0x0})));
+      o->s = y;
+    }
+    case 0xB: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,1));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {~0x0, ~0x0, 0x0, ~0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, 0x0, ~0x0, 0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      break;
+    }
+    case 0xC: {
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {~0x0, ~0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, 0x0, ~0x0, ~0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      break;
+    }
+    case 0xD: {
+      const float32x4_t x = vdupq_n_f32(vgetq_lane_f32(bIn0,0));
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {~0x0, 0x0, ~0x0, ~0x0}),
+          vandq_u32(vreinterpretq_u32_f32(x), (uint32x4_t) {0x0, ~0x0, 0x0, 0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+    }
+    case 0xE: {
+      *bOut = vreinterpretq_f32_u32(vorrq_u32(
+          vandq_u32(vreinterpretq_u32_f32(o->s), (uint32x4_t) {~0x0, 0x0, 0x0, 0x0}),
+          vandq_u32(vreinterpretq_u32_f32(bIn0), (uint32x4_t) {0x0, ~0x0, ~0x0, ~0x0})));
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      break;
+    }
+    case 0xF: {
+      *bOut = bIn0;
+      o->s = vdupq_n_f32(vgetq_lane_f32(bIn0,3));
+      break;
+    }
+  }
+#else // HV_SIMD_NONE
+  if (bIn1 != 0.0f) o->s = bIn0;
+  *bOut = o->s;
+#endif
+}
+
+void sSamphold_onMessage(HvBase *_c, SignalSamphold *o, int letIndex,
+    const HvMessage *const m, void *sendMessage);
+
+#endif // _SIGNAL_SAMPHOLD_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalVar.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "SignalVar.h"
+
+// __var~f
+
+static void sVarf_update(SignalVarf *o, float k, float step, bool reverse) {
+#if HV_SIMD_AVX
+  if (reverse) o->v = _mm256_setr_ps(k+7.0f*step, k+6.0f*step, k+5.0f*step, k+4.0f*step, k+3.0f*step, k+2.0f*step, k+step, k);
+  else o->v = _mm256_set_ps(k+7.0f*step, k+6.0f*step, k+5.0f*step, k+4.0f*step, k+3.0f*step, k+2.0f*step, k+step, k);
+#elif HV_SIMD_SSE
+  if (reverse) o->v = _mm_setr_ps(k+3.0f*step, k+2.0f*step, k+step, k);
+  else o->v = _mm_set_ps(k+3.0f*step, k+2.0f*step, k+step, k);
+#elif HV_SIMD_NEON
+  if (reverse) o->v = (float32x4_t) {3.0f*step+k, 2.0f*step+k, step+k, k};
+  else o->v = (float32x4_t) {k, step+k, 2.0f*step+k, 3.0f*step+k};
+#else // HV_SIMD_NONE
+  o->v = k;
+#endif
+}
+
+hv_size_t sVarf_init(SignalVarf *o, float k, float step, bool reverse) {
+  sVarf_update(o, k, step, reverse);
+  return 0;
+}
+
+void sVarf_onMessage(HvBase *_c, SignalVarf *o, const HvMessage *m) {
+  if (msg_isFloat(m,0)) {
+    sVarf_update(o, msg_getFloat(m,0), msg_isFloat(m,1) ? msg_getFloat(m,1) : 0.0f, msg_getNumElements(m) == 3);
+  }
+}
+
+
+
+// __var~i
+
+static void sVari_update(SignalVari *o, int k, int step, bool reverse) {
+#if HV_SIMD_AVX
+  if (reverse) o->v = _mm256_setr_epi32(k+7*step, k+6*step, k+5*step, k+4*step, k+3*step, k+2*step, k+step, k);
+  else o->v = _mm256_set_epi32(k+7*step, k+6*step, k+5*step, k+4*step, k+3*step, k+2*step, k+step, k);
+#elif HV_SIMD_SSE
+  if (reverse) o->v = _mm_setr_epi32(k+3*step, k+2*step, k+step, k);
+  else o->v = _mm_set_epi32(k+3*step, k+2*step, k+step, k);
+#elif HV_SIMD_NEON
+  if (reverse) o->v = (int32x4_t) {3*step+k, 2*step+k, step+k, k};
+  else o->v = (int32x4_t) {k, step+k, 2*step+k, 3*step+k};
+#else // HV_SIMD_NEON
+  o->v = k;
+#endif
+}
+
+hv_size_t sVari_init(SignalVari *o, int k, int step, bool reverse) {
+  sVari_update(o, k, step, reverse);
+  return 0;
+}
+
+void sVari_onMessage(HvBase *_c, SignalVari *o, const HvMessage *m) {
+  if (msg_isFloat(m,0)) {
+    sVari_update(o, (int) msg_getFloat(m,0), msg_isFloat(m,1) ? (int) msg_getFloat(m,1) : 0, msg_getNumElements(m) == 3);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/SignalVar.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_SIGNAL_VAR_H_
+#define _HEAVY_SIGNAL_VAR_H_
+
+#include "HvBase.h"
+
+// __var~f
+// __varset~f
+
+typedef struct SignalVarf {
+  hv_bufferf_t v;
+} SignalVarf;
+
+hv_size_t sVarf_init(SignalVarf *o, float k, float step, bool reverse);
+
+static inline void __hv_var_f(SignalVarf *o, hv_bOutf_t bOut) {
+  *bOut = o->v;
+}
+
+static inline void sVarsetf_process(SignalVarf *o, hv_bInf_t bIn) {
+  o->v = bIn;
+}
+
+void sVarf_onMessage(HvBase *_c, SignalVarf *o, const HvMessage *m);
+
+
+
+// __var~i
+// __varset~i
+
+typedef struct SignalVari {
+  hv_bufferi_t v;
+} SignalVari;
+
+hv_size_t sVari_init(SignalVari *o, int k, int step, bool reverse);
+
+static inline void __hv_var_i(SignalVari *o, hv_bOuti_t bOut) {
+  *bOut = o->v;
+}
+
+#if HV_SIMD_AVX
+#define __hv_var_k_i_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m256i)(__v8si) {_a,_b,_c,_d,_e,_f,_g,_h})
+#define __hv_var_k_i_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m256i)(__v8si) {_h,_g,_f,_e,_d,_c,_b,_a})
+#define __hv_var_k_f_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m256) {_a,_b,_c,_d,_e,_f,_g,_h})
+#define __hv_var_k_f_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m256) {_h,_g,_f,_e,_d,_c,_b,_a})
+#elif HV_SIMD_SSE
+#define __hv_var_k_i_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m128i)(__v4si) {_a,_b,_c,_d})
+#define __hv_var_k_i_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m128i)(__v4si) {_d,_c,_b,_a})
+#define __hv_var_k_f_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m128) {_a,_b,_c,_d})
+#define __hv_var_k_f_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((__m128) {_d,_c,_b,_a})
+#elif HV_SIMD_NEON
+#define __hv_var_k_i_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((int32x4_t) {_a,_b,_c,_d})
+#define __hv_var_k_i_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((int32x4_t) {_d,_c,_b,_a})
+#define __hv_var_k_f_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((float32x4_t) {_a,_b,_c,_d})
+#define __hv_var_k_f_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=((float32x4_t) {_d,_c,_b,_a})
+#else // HV_SIMD_NONE
+#define __hv_var_k_i_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a
+#define __hv_var_k_i_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a
+#define __hv_var_k_f_0(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a
+#define __hv_var_k_f_1(_z,_a,_b,_c,_d,_e,_f,_g,_h) *_z=_a
+#endif
+// r == 0: forwards, r == 1: backwards
+#define __hv_var_k_i(_z,_a,_b,_c,_d,_e,_f,_g,_h,_r) __hv_var_k_i_##_r(_z,_a,_b,_c,_d,_e,_f,_g,_h)
+#define __hv_var_k_f(_z,_a,_b,_c,_d,_e,_f,_g,_h,_r) __hv_var_k_f_##_r(_z,_a,_b,_c,_d,_e,_f,_g,_h)
+
+static inline void sVarseti_process(SignalVari *o, hv_bIni_t bIn) {
+  o->v = bIn;
+}
+
+void sVari_onMessage(HvBase *_c, SignalVari *o, const HvMessage *m);
+
+#endif // _HEAVY_SIGNAL_VAR_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Utils.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,177 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_UTILS_H_
+#define _HEAVY_UTILS_H_
+
+// Type definitions
+#if _WIN32 || _WIN64 || WINAPI_FAMILY
+#define HV_WIN 1
+#include <stddef.h>
+#if defined (_MSC_VER)
+#define HV_MSVC 1
+#endif
+#define hv_size_t unsigned long
+#define hv_uint32_t unsigned int
+#define hv_uint16_t unsigned short
+#define hv_int32_t int
+#elif __APPLE__ && __MACH__
+#define HV_APPLE 1
+#include <stddef.h>
+#define hv_size_t size_t
+#define hv_uint32_t unsigned int
+#define hv_uint16_t unsigned short
+#define hv_int32_t int
+#elif __unix__ || __unix
+#define HV_UNIX 1
+#include <stddef.h>
+#include <stdint.h>
+#define hv_size_t size_t
+#define hv_uint32_t uint32_t
+#define hv_uint16_t uint16_t
+#define hv_int32_t int32_t
+#else
+#error Unsupported platform
+#endif
+
+// Memory management
+extern void *hv_alloca(hv_size_t numbytes);
+extern void *hv_malloc(hv_size_t numbytes); // allocates memory on 16 byte boundaries and clears it to zero
+extern void hv_free(void *ptr); // frees aligned memory
+extern void *hv_realloc(void *ptr, hv_size_t numBytes);
+extern void *hv_memcpy(void *dest, const void *src, hv_size_t numbytes);
+extern void *hv_memset(void *ptr, hv_size_t numbytes); // sets everything to 0
+
+// String handling
+extern hv_size_t hv_strlen(const char *str);
+extern char *hv_strncat(char *dest, const char *str, hv_size_t n);
+extern char *hv_strncpy(char *dest, const char *str, hv_size_t n);
+extern int hv_strcmp(const char *str1, const char *str2);
+extern int hv_strncmp(const char *str1, const char *str2, hv_size_t n);
+extern int hv_snprintf(char *dest, hv_size_t n, const char *format, ...);
+
+// Math
+extern int hv_max_i(int x, int y);
+extern hv_size_t hv_max_ui(hv_size_t x, hv_size_t y);
+extern int hv_min_i(int x, int y);
+extern hv_size_t hv_min_ui(hv_size_t x, hv_size_t y);
+extern float hv_max_f(float x, float y);
+extern float hv_min_f(float x, float y);
+extern double hv_max_d(double x, double y);
+extern double hv_min_d(double x, double y);
+extern float hv_sin_f(float x);
+extern float hv_sinh_f(float x);
+extern float hv_cos_f(float x);
+extern float hv_cosh_f(float x);
+extern float hv_tan_f(float x);
+extern float hv_tanh_f(float x);
+extern float hv_asin_f(float x);
+extern float hv_asinh_f(float x);
+extern float hv_acos_f(float x);
+extern float hv_acosh_f(float x);
+extern float hv_atan_f(float x);
+extern float hv_atanh_f(float x);
+extern float hv_atan2_f(float x, float y);
+extern float hv_exp_f(float x);
+extern float hv_abs_f(float x);
+extern float hv_sqrt_f(float x);
+extern float hv_log_f(float x);
+extern float hv_log2_f(float x);
+extern float hv_log10_f(float x);
+extern float hv_ceil_f(float x);
+extern float hv_floor_f(float x);
+extern float hv_round_f(float x);
+extern float hv_pow_f(float x, float y);
+extern float hv_fma_f(float x, float y, float z);
+
+// Utilities
+extern void hv_assert(int e);
+extern void hv_clear_buffer(float *b, int n);
+extern hv_uint32_t hv_min_max_log2(hv_uint32_t x);
+
+// SIMD
+#ifndef HV_SIMD_NONE
+  #define HV_SIMD_NEON __ARM_NEON__
+  #define HV_SIMD_SSE (__SSE__ && __SSE2__ && __SSE3__ && __SSSE3__ && __SSE4_1__)
+  #define HV_SIMD_AVX (__AVX__ && HV_SIMD_SSE) // it is required that if AVX exists then SSE will also be available
+  #define HV_SIMD_FMA __FMA__
+#endif
+
+#ifdef HV_WIN
+#include "Utils_windows.h"
+#elif HV_APPLE
+#include "Utils_mac.h"
+#elif HV_UNIX
+#include "Utils_unix.h"
+#else
+#error Unsupported platform
+#endif
+
+#if HV_SIMD_NEON // NEON
+  #define HV_N_SIMD 4
+  #define hv_bufferf_t float32x4_t
+  #define hv_bufferi_t int32x4_t
+  #define hv_bInf_t float32x4_t
+  #define hv_bOutf_t float32x4_t*
+  #define hv_bIni_t int32x4_t
+  #define hv_bOuti_t int32x4_t*
+  #define VIf(_x) (_x)
+  #define VOf(_x) (&_x)
+  #define VIi(_x) (_x)
+  #define VOi(_x) (&_x)
+#elif HV_SIMD_AVX // AVX
+  #define HV_N_SIMD 8
+  #define hv_bufferf_t __m256
+  #define hv_bufferi_t __m256i
+  #define hv_bInf_t __m256
+  #define hv_bOutf_t __m256*
+  #define hv_bIni_t __m256i
+  #define hv_bOuti_t __m256i*
+  #define VIf(_x) (_x)
+  #define VOf(_x) (&_x)
+  #define VIi(_x) (_x)
+  #define VOi(_x) (&_x)
+#elif HV_SIMD_SSE // SSE
+  #define HV_N_SIMD 4
+  #define hv_bufferf_t __m128
+  #define hv_bufferi_t __m128i
+  #define hv_bInf_t __m128
+  #define hv_bOutf_t __m128*
+  #define hv_bIni_t __m128i
+  #define hv_bOuti_t __m128i*
+  #define VIf(_x) (_x)
+  #define VOf(_x) (&_x)
+  #define VIi(_x) (_x)
+  #define VOi(_x) (&_x)
+#else // DEFAULT
+  #define HV_N_SIMD 1
+  #undef HV_SIMD_NONE
+  #define HV_SIMD_NONE 1
+  #define hv_bufferf_t float
+  #define hv_bufferi_t int
+  #define hv_bInf_t float
+  #define hv_bOutf_t float*
+  #define hv_bIni_t int
+  #define hv_bOuti_t int*
+  #define VIf(_x) (_x)
+  #define VOf(_x) (&_x)
+  #define VIi(_x) (_x)
+  #define VOi(_x) (&_x)
+#endif
+
+#define HV_N_SIMD_MASK (HV_N_SIMD-1)
+
+#endif // _HEAVY_UTILS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Utils_mac.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "Utils_mac.h"
+
+#if HV_APPLE
+
+hv_size_t hv_max_ui(hv_size_t x, hv_size_t y) {
+  return (x >= y) ? x : y;
+}
+
+hv_size_t hv_min_ui(hv_size_t x, hv_size_t y) {
+  return (x <= y) ? x : y;
+}
+
+int hv_max_i(int x, int y) {
+  return (x >= y) ? x : y;
+}
+
+int hv_min_i(int x, int y) {
+  return (x <= y) ? x : y;
+}
+
+hv_uint32_t hv_min_max_log2(hv_uint32_t x) {
+  // finds ceil(log2(x))
+  // http://stackoverflow.com/questions/2589096/find-most-significant-bit-left-most-that-is-set-in-a-bit-array
+  return (hv_uint32_t) ((8 * sizeof(unsigned int)) - __builtin_clz(x - 1));
+}
+
+#endif // HV_APPLE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Utils_mac.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_UTILS_MAC_H_
+#define _HEAVY_UTILS_MAC_H_
+
+#include "Utils.h"
+
+#if HV_APPLE
+#include <alloca.h>
+#if HV_SIMD_AVX || HV_SIMD_SSE
+#include <immintrin.h>
+#include <mm_malloc.h>
+#elif HV_SIMD_NEON
+#include <arm_neon.h>
+#endif
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define HV_EXPORT
+#define HV_FORCE_INLINE inline __attribute__((always_inline))
+
+// Memory management
+#define hv_alloca(_n) alloca(_n)
+#if HV_SIMD_AVX || HV_SIMD_SSE
+  #define hv_malloc(_n) _mm_malloc(_n, 32) // 32 to ensure AVX compatability (16 otherwise)
+  #define hv_free(x) _mm_free(x)
+#else
+  #define hv_malloc(_n) malloc(_n)
+  #define hv_free(x) free(x)
+#endif
+#define hv_realloc(a, b) realloc(a, b)
+#define hv_memcpy(a, b, c) memcpy(a, b, c)
+#define hv_memset(a, b) memset(a, 0, b)
+
+// Strings
+#define hv_strlen(a) strlen(a)
+#define hv_strncat(a, b, c) strncat(a, b, c)
+#define hv_strncpy(a, b, c) strncpy(a, b, c)
+#define hv_strcmp(a, b) strcmp(a, b)
+#define hv_strncmp(a, b, c) strncmp(a, b, c)
+#define hv_snprintf(a, b, c, ...) snprintf(a, b, c, __VA_ARGS__)
+
+// Math
+#define hv_max_f(a, b) fmaxf(a, b)
+#define hv_min_f(a, b) fminf(a, b)
+#define hv_max_d(a, b) fmax(a, b)
+#define hv_min_d(a, b) fmin(a, b)
+#define hv_sin_f(a) sinf(a)
+#define hv_sinh_f(a) sinhf(a)
+#define hv_cos_f(a) cosf(a)
+#define hv_cosh_f(a) coshf(a)
+#define hv_tan_f(a) tanf(a)
+#define hv_tanh_f(a) tanhf(a)
+#define hv_asin_f(a) asinf(a)
+#define hv_asinh_f(a) asinhf(a)
+#define hv_acos_f(a) acosf(a)
+#define hv_acosh_f(a) acoshf(a)
+#define hv_atan_f(a) atanf(a)
+#define hv_atanh_f(a) atanhf(a)
+#define hv_atan2_f(a, b) atan2f(a, b)
+#define hv_exp_f(a) expf(a)
+#define hv_abs_f(a) fabsf(a)
+#define hv_sqrt_f(a) sqrtf(a)
+#define hv_log_f(a) logf(a)
+#define hv_log2_f(a) log2f(a)
+#define hv_log10_f(a) log10f(a)
+#define hv_ceil_f(a) ceilf(a)
+#define hv_floor_f(a) floorf(a)
+#define hv_round_f(a) roundf(a)
+#define hv_pow_f(a, b) powf(a, b)
+#define hv_fma_f(a, b, c) ((a*b)+c) // TODO(joe): use 'fmaf(a, b, c)' once emscripten supports it
+
+// Utilities
+#define hv_assert(e) assert(e)
+#define hv_clear_buffer(b, n) memset(b, 0, (n)*sizeof(float))
+
+#endif // HV_APPLE
+#endif // _HEAVY_UTILS_MAC_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Utils_unix.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "Utils_unix.h"
+
+#if HV_UNIX
+
+hv_size_t hv_max_ui(hv_size_t x, hv_size_t y) {
+  return (x >= y) ? x : y;
+}
+
+hv_size_t hv_min_ui(hv_size_t x, hv_size_t y) {
+  return (x <= y) ? x : y;
+}
+
+int hv_max_i(int x, int y) {
+  return (x >= y) ? x : y;
+}
+
+int hv_min_i(int x, int y) {
+  return (x <= y) ? x : y;
+}
+
+hv_uint32_t hv_min_max_log2(hv_uint32_t x) {
+  // finds ceil(log2(x))
+  // http://stackoverflow.com/questions/2589096/find-most-significant-bit-left-most-that-is-set-in-a-bit-array
+  return (hv_uint32_t) ((8 * sizeof(unsigned int)) - __builtin_clz(x - 1));
+}
+
+#endif // HV_UNIX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Utils_unix.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_UTILS_UNIX_H_
+#define _HEAVY_UTILS_UNIX_H_
+
+#include "Utils.h"
+
+#if HV_UNIX
+#if HV_SIMD_AVX || HV_SIMD_SSE
+#include <immintrin.h>
+#include <mm_malloc.h>
+#elif HV_SIMD_NEON
+#include <arm_neon.h>
+#endif
+#include <alloca.h>
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define HV_EXPORT
+#define HV_FORCE_INLINE inline __attribute__((always_inline))
+
+// Memory management
+#define hv_alloca(_n) alloca(_n)
+#if HV_SIMD_AVX || HV_SIMD_SSE
+  #define hv_malloc(_n) _mm_malloc(_n, 32) // 32 to ensure AVX compatability (16 otherwise)
+  #define hv_free(x) _mm_free(x)
+#else
+  #define hv_malloc(_n) malloc(_n)
+  #define hv_free(_n) free(_n)
+#endif
+#define hv_realloc(a, b) realloc(a, b)
+#define hv_memcpy(a, b, c) memcpy(a, b, c)
+#define hv_memset(a, b) memset(a, 0, b)
+
+// Strings
+#define hv_strlen(a) strlen(a)
+#define hv_strncat(a, b, c) strncat(a, b, c)
+#define hv_strncpy(a, b, c) strncpy(a, b, c)
+#define hv_strcmp(a, b) strcmp(a, b)
+#define hv_strncmp(a, b, c) strncmp(a, b, c)
+#define hv_snprintf(a, b, c, ...) snprintf(a, b, c, __VA_ARGS__)
+
+// Math
+#define hv_max_f(a, b) fmaxf(a, b)
+#define hv_min_f(a, b) fminf(a, b)
+#define hv_max_d(a, b) fmax(a, b)
+#define hv_min_d(a, b) fmin(a, b)
+#define hv_sin_f(a) sinf(a)
+#define hv_sinh_f(a) sinhf(a)
+#define hv_cos_f(a) cosf(a)
+#define hv_cosh_f(a) coshf(a)
+#define hv_tan_f(a) tanf(a)
+#define hv_tanh_f(a) tanhf(a)
+#define hv_asin_f(a) asinf(a)
+#define hv_asinh_f(a) asinhf(a)
+#define hv_acos_f(a) acosf(a)
+#define hv_acosh_f(a) acoshf(a)
+#define hv_atan_f(a) atanf(a)
+#define hv_atanh_f(a) atanhf(a)
+#define hv_atan2_f(a, b) atan2f(a, b)
+#define hv_exp_f(a) expf(a)
+#define hv_abs_f(a) fabsf(a)
+#define hv_sqrt_f(a) sqrtf(a)
+#define hv_log_f(a) logf(a)
+#define hv_log2_f(a) log2f(a)
+#define hv_log10_f(a) log10f(a)
+#define hv_ceil_f(a) ceilf(a)
+#define hv_floor_f(a) floorf(a)
+#define hv_round_f(a) roundf(a)
+#define hv_pow_f(a, b) powf(a, b)
+#define hv_fma_f(a, b, c) ((a*b)+c) // TODO(joe): use 'fmaf(a, b, c)' once emscripten supports it
+
+// Utilities
+#define hv_assert(e) assert(e)
+#define hv_clear_buffer(b, n) memset(b, 0, n*sizeof(float))
+
+#endif // HV_UNIX
+#endif // _HEAVY_UTILS_UNIX_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Utils_windows.c	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "Utils_windows.h"
+
+#if HV_WIN
+
+hv_size_t hv_max_ui(hv_size_t x, hv_size_t y) {
+  return (x >= y) ? x : y;
+}
+
+hv_size_t hv_min_ui(hv_size_t x, hv_size_t y) {
+  return (x <= y) ? x : y;
+}
+
+int hv_max_i(int x, int y) {
+  return (x >= y) ? x : y;
+}
+
+int hv_min_i(int x, int y) {
+  return (x <= y) ? x : y;
+}
+
+hv_uint32_t hv_min_max_log2(hv_uint32_t x) {
+#if HV_MSVC
+  // finds ceil(log2(x))
+  // http://stackoverflow.com/questions/2589096/find-most-significant-bit-left-most-that-is-set-in-a-bit-array
+  // http://msdn.microsoft.com/en-us/library/fbxyd7zd%28v=VS.80%29.aspx
+  unsigned long z = 0;
+  _BitScanReverse(&z, x);
+  return (hv_uint32_t) (z+1);
+#else
+  return (hv_uint32_t) ((8 * sizeof(unsigned int)) - __builtin_clz(x-1));
+#endif // HV_MSVC
+}
+
+#if HV_MSVC
+int hv_snprintf(char* str, hv_size_t size, const char* format, ...) {
+  // http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+	int count = -1;
+	va_list ap;
+	va_start(ap, format);
+
+	if (size != 0) {
+		count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
+	}
+	if (count == -1) {
+		count = _vscprintf(format, ap);
+	}
+	va_end(ap);
+	return count;
+}
+#endif // HV_MSVC
+#endif // HV_WIN
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/Utils_windows.h	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) 2014, 2015, Enzien Audio Ltd.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HEAVY_UTILS_WINDOWS_H_
+#define _HEAVY_UTILS_WINDOWS_H_
+
+#include "Utils.h"
+
+#if HV_WIN
+#define _USE_MATH_DEFINES
+#if HV_SIMD_AVX || HV_SIMD_SSE
+#if HV_MSVC
+#include <intrin.h>
+#else
+#include <immintrin.h>
+#endif
+#elif HV_SIMD_NEON
+#include <arm_neon.h>
+#endif
+#include <malloc.h>
+#include <assert.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define HV_EXPORT __declspec(dllexport)
+
+// MSVC Specific
+#if HV_MSVC
+#define inline __inline
+#define HV_FORCE_INLINE __forceinline
+#else
+#define HV_FORCE_INLINE inline __attribute__((always_inline))
+#define hv_snprintf(a, b, c, ...) snprintf(a, b, c, __VA_ARGS__)
+#endif // HV_MSVC
+
+// Memory management
+#define hv_alloca(_n) _alloca(_n)
+#if !defined(HV_SIMD_AVX) || !defined(HV_SIMD_SSE)
+#define hv_malloc(_n) _aligned_malloc(_n, 32)
+#define hv_free(x) _aligned_free(x)
+#else
+#define hv_malloc(_n) malloc(_n)
+#define hv_free(_n) free(_n)
+#endif
+#define hv_realloc(a, b) realloc(a, b)
+#define hv_memcpy(a, b, c) memcpy(a, b, c)
+#define hv_memset(a, b) memset(a, 0, b)
+
+// Strings
+#define hv_strncat(a, b, c) strncat(a, b, c)
+#define hv_strcmp(a, b) strcmp(a, b)
+#define hv_strncmp(a, b, c) strncmp(a, b, c)
+#define hv_strncpy(a, b, c) strncpy(a, b, c)
+#define hv_strlen(a) strlen(a)
+
+// Math
+#define hv_max_f(a, b) fmaxf(a, b)
+#define hv_min_f(a, b) fminf(a, b)
+#define hv_max_d(a, b) fmax(a, b)
+#define hv_min_d(a, b) fmin(a, b)
+#define hv_sin_f(a) sinf(a)
+#define hv_sinh_f(a) sinhf(a)
+#define hv_cos_f(a) cosf(a)
+#define hv_cosh_f(a) coshf(a)
+#define hv_tan_f(a) tanf(a)
+#define hv_tanh_f(a) tanhf(a)
+#define hv_asin_f(a) asinf(a)
+#define hv_asinh_f(a) asinhf(a)
+#define hv_acos_f(a) acosf(a)
+#define hv_acosh_f(a) acoshf(a)
+#define hv_atan_f(a) atanf(a)
+#define hv_atanh_f(a) atanhf(a)
+#define hv_atan2_f(a, b) atan2f(a, b)
+#define hv_exp_f(a) expf(a)
+#define hv_abs_f(a) fabsf(a)
+#define hv_sqrt_f(a) sqrtf(a)
+#define hv_log_f(a) logf(a)
+#define hv_log2_f(a) log2f(a)
+#define hv_log10_f(a) log10f(a)
+#define hv_ceil_f(a) ceilf(a)
+#define hv_floor_f(a) floorf(a)
+#define hv_round_f(a) roundf(a)
+#define hv_pow_f(a, b) powf(a, b)
+#define hv_fma_f(a, b, c) ((a*b)+c) // TODO(joe): use 'fmaf(a, b, c)' once emscripten supports it
+
+// Utilities
+#define hv_assert(e) assert(e)
+#define hv_clear_buffer(b, n) memset(b, 0, n*sizeof(float))
+
+#endif // HV_WIN
+#endif // _HEAVY_UTILS_WINDOWS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/heavy/samphold/render.cpp	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,183 @@
+/*
+ * render.cpp
+ *
+ *  Template render.cpp file for on-board heavy compiling
+ *
+ *  N.B. this is currently *not* compatible with foleyDesigner source files!
+ *
+ *  Created on: November 5, 2015
+ *
+ *  Christian Heinrichs
+ *
+ */
+
+#include <BeagleRT.h>
+#include <cmath>
+#include "../include/Utilities.h"
+#include "Heavy_bbb.h"
+
+// #include "I2c_TouchKey.h"
+
+// #include "../include/UdpServer.h"
+// #include "../include/UdpClient.h"
+// #include <iostream>
+// #include <fstream>
+// #include "../include/ReceiveAudioThread.h"
+
+// #include "../include/render.h"
+// #include <arm_neon.h>
+// #include <time.h>
+// #include <sndfile.h>
+
+// #include "../include/RTAudio.h"
+// #include <rtdk.h>
+
+
+/*
+ *	HEAVY CONTEXT & BUFFERS
+ */
+
+Hv_bbb *gHeavyContext;
+float *gHvInputBuffers = NULL, *gHvOutputBuffers = NULL;
+int gHvInputChannels = 0, gHvOutputChannels = 0;
+
+float gInverseSampleRate;
+
+/*
+ *	HEAVY FUNCTIONS
+ */
+
+void printHook(double timestampSecs, const char *printLabel, const char *msgString, void *userData) {
+  printf("Message from Heavy patch: [@ %.3f] %s: %s\n", timestampSecs, printLabel, msgString);
+}
+
+static void sendHook(
+    double timestamp, // in milliseconds
+    const char *receiverName,
+    const HvMessage *const m,
+    void *userData) {
+
+  // only react to messages sent to receivers named "hello"
+  if (!strncmp(receiverName, "hello", 5)) {
+  }
+
+}
+
+/*
+ * RENDER INITIALISATION, LOOP & CLEANUP
+ */
+
+
+// bool initialise_render(int numMatrixChannels, int numAudioChannels,
+// 					   int numMatrixFramesPerPeriod,
+// 					   int numAudioFramesPerPeriod,
+// 					   float matrixSampleRate, float audioSampleRate,
+// 					   void *userData)
+// {
+bool setup(BeagleRTContext *context, void *userData)	{
+
+	/* HEAVY */
+
+	gHeavyContext = hv_bbb_new(context->audioSampleRate);
+
+	gHvInputChannels = hv_getNumInputChannels(gHeavyContext);
+	gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext);
+
+	// srand ( time(NULL) );  	
+
+	rt_printf("Starting Heavy context with %d input channels and %d output channels\n",
+			  gHvInputChannels, gHvOutputChannels);
+
+	if(gHvInputChannels != 0) {
+		gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float));
+		//memset(gHvInputBuffers,0,gHvInputChannels * numAudioFramesPerPeriod * sizeof(float));
+	}
+	if(gHvOutputChannels != 0) {
+		gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float));
+	}
+
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+
+	// Set heavy print hook
+	hv_setPrintHook(gHeavyContext, &printHook);
+	// Set heavy send hook
+	hv_setSendHook(gHeavyContext, sendHook);
+
+	return true;
+}
+
+
+// void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
+// 			uint16_t *matrixIn, uint16_t *matrixOut)
+// {	
+void render(BeagleRTContext *context, void *userData)
+{
+	// use this for thread management
+	// if(gCount == 0) {
+	// } else {
+	// }
+	// gCount++;
+
+	// De-interleave the data
+	if(gHvInputBuffers != NULL) {
+		for(int n = 0; n < context->audioFrames; n++) {
+			for(int ch = 0; ch < gHvInputChannels; ch++) {
+				if(ch >= context->audioChannels+context->analogChannels) {
+					// THESE ARE PARAMETER INPUT 'CHANNELS' USED FOR ROUTING
+					// 'sensor' outputs from routing channels of dac~ are passed through here
+					break;
+				} else {
+					// If more than 2 ADC inputs are used in the pd patch, route the analog inputs
+					// i.e. ADC3->analogIn0 etc. (first two are always audio inputs)
+					if(ch >= context->audioChannels)	{
+						int m = n/2;
+						float mIn = context->analogIn[m*context->analogChannels + (ch-context->audioChannels)];
+						gHvInputBuffers[ch * context->audioFrames + n] = mIn;
+					} else {
+						gHvInputBuffers[ch * context->audioFrames + n] = context->audioIn[n * context->audioChannels + ch];
+					}
+				}
+			}
+		}
+	}
+
+	// replacement for bang~ object
+	//hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b");
+
+	hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames);
+
+	// Interleave the output data
+	if(gHvOutputBuffers != NULL) {
+		for(int n = 0; n < context->audioFrames; n++) {
+
+			for(int ch = 0; ch < gHvOutputChannels; ch++) {
+				if(ch >= context->audioChannels+context->analogChannels) {
+					// THESE ARE SENSOR OUTPUT 'CHANNELS' USED FOR ROUTING
+					// they are the content of the 'sensor output' dac~ channels
+				} else {
+					if(ch >= context->audioChannels)	{
+						int m = n/2;
+						// float mOut = (float)gHvOutputBuffers[ch*numAudioFrames + n];
+						// mOut = constrain(mOut,0.0,1.0);
+						context->analogOut[m * context->analogFrames + (ch-context->audioChannels)] = constrain(gHvOutputBuffers[ch*context->audioFrames + n],0.0,1.0);
+					} else {
+						context->audioOut[n * context->audioChannels + ch] = gHvOutputBuffers[ch * context->audioFrames + n];
+					}
+				}
+			}
+		}
+	}
+
+}
+
+
+void cleanup(BeagleRTContext *context, void *userData)
+{
+
+	hv_bbb_free(gHeavyContext);
+	if(gHvInputBuffers != NULL)
+		free(gHvInputBuffers);
+	if(gHvOutputBuffers != NULL)
+		free(gHvOutputBuffers);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/build_pd.sh	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,107 @@
+#!/bin/bash
+
+# shell script for automatic uploading/compiling of pd patch onto bbb
+# Christian Heinrichs 2015
+#
+# example usage: sh upload-and-compile.sh -f bwg-tests -q -e
+
+workingdir=".."
+verbose="0"
+render="0"
+pdpath=""
+projectpath="../projects/heavy/hvtemp"
+BBB_PATH="~/BeagleRT"
+BBB_ADDRESS="root@192.168.7.2"
+COMMAND_ARGS=
+RUN_PROJECT=1
+RUN_IN_FOREGROUND=0
+RUN_WITHOUT_SCREEN=1
+
+function usage
+{
+    echo "
+    USAGE: build_pd.sh [[-i input folder containing _main.pd file ] [-o output folder for new heavy project .c files (default ../projects/heavy/hvtemp)] [-b bbb path to copy to (default ~/BeagleRT)] | [-h]]
+    "    
+    echo "example: build_pd.sh -i ../projects/heavy/pd/hello-world -o ../projects/heavy/hello-world"
+}
+
+while [ "$1" != "" ]; do
+    case $1 in
+        -b | --bbb )            shift
+                                BBB_PATH=$1
+                                ;;
+        -i | --input )          shift
+                                pdpath=$1
+                                ;;
+        -o | --output )         shift
+                                projectpath=$1
+                                ;;
+        -v | --verbose )        shift
+                                verbose=1
+                                ;;
+        -r | --render )         shift
+                                render=1
+                                ;;
+        -h | --help )           usage
+                                exit
+                                ;;
+        * )                     usage
+                                exit 1
+    esac
+    shift
+done
+
+/usr/bin/python hvresources/uploader.py "$pdpath"/ -n bbb -g c -o "$projectpath"/;
+if [ $? -ne 0 ]; then
+    /usr/local/bin/python hvresources/uploader.py "$pdpath"/ -n bbb -g c -o "$projectpath"/;
+    if [ $? -ne 0 ]; then
+        #echo "ERROR: an error occurred while executing the uploader.py script"
+        echo "error"
+        exit 1
+    fi;
+fi;
+echo "";
+#echo "*|*|* Successfully uploaded and converted pd patch into super-fast optimized C code. Brought to you by Heavy! *|*|*";
+echo "";
+
+# check how to copy/sync render.cpp file...
+if [ $render -eq 0 ]; then
+    cp "hvresources/render.cpp" $projectpath/;
+fi;
+
+rsync -c -r "$projectpath"/ "$BBB_ADDRESS":"$BBB_PATH"/source;
+
+if [ $? -ne 0 ]; then
+    echo "";
+    echo ":( :( :( ERROR: while synchronizing files with the BBB. Is the board connected and the correct SD card inserted? :( :( :(";
+    echo "";
+    exit 1;
+fi;
+
+# Make new BeagleRT executable and run
+if [ $RUN_PROJECT -eq 0 ]
+then
+    echo "Building project..."
+    ssh $BBB_ADDRESS "make all -C $BBB_PATH"
+else
+    echo "Building and running project..."
+    
+    if [ $RUN_WITHOUT_SCREEN -ne 0 ]
+    then
+        ssh -t $BBB_ADDRESS "make all -C $BBB_PATH && $BBB_PATH/BeagleRT $COMMAND_ARGS" 
+    elif [ $RUN_IN_FOREGROUND -eq 0 ]
+    then
+        ssh $BBB_ADDRESS "make all -C $BBB_PATH && screen -S BeagleRT -d -m $BBB_PATH/BeagleRT $COMMAND_ARGS"
+    else
+        ssh -t $BBB_ADDRESS "make all -C $BBB_PATH && screen -S BeagleRT $BBB_PATH/BeagleRT $COMMAND_ARGS"
+    fi
+fi
+
+
+
+
+
+
+
+
+#ssh -t root@192.168.7.2 "kill -s 2 \`pidof heavy_template\` 2>/dev/null; sleep 0.5; rm -f ~/$filename_bbb/Release/source/heavy/HvContext_bbb.? ~/$filename_bbb/Release/heavy_template && make all -C ~/$filename_bbb/Release" &>/dev/null
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/hvresources/render.cpp	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,183 @@
+/*
+ * render.cpp
+ *
+ *  Template render.cpp file for on-board heavy compiling
+ *
+ *  N.B. this is currently *not* compatible with foleyDesigner source files!
+ *
+ *  Created on: November 5, 2015
+ *
+ *  Christian Heinrichs
+ *
+ */
+
+#include <BeagleRT.h>
+#include <cmath>
+#include "../include/Utilities.h"
+#include "Heavy_bbb.h"
+
+// #include "I2c_TouchKey.h"
+
+// #include "../include/UdpServer.h"
+// #include "../include/UdpClient.h"
+// #include <iostream>
+// #include <fstream>
+// #include "../include/ReceiveAudioThread.h"
+
+// #include "../include/render.h"
+// #include <arm_neon.h>
+// #include <time.h>
+// #include <sndfile.h>
+
+// #include "../include/RTAudio.h"
+// #include <rtdk.h>
+
+
+/*
+ *	HEAVY CONTEXT & BUFFERS
+ */
+
+Hv_bbb *gHeavyContext;
+float *gHvInputBuffers = NULL, *gHvOutputBuffers = NULL;
+int gHvInputChannels = 0, gHvOutputChannels = 0;
+
+float gInverseSampleRate;
+
+/*
+ *	HEAVY FUNCTIONS
+ */
+
+void printHook(double timestampSecs, const char *printLabel, const char *msgString, void *userData) {
+  printf("Message from Heavy patch: [@ %.3f] %s: %s\n", timestampSecs, printLabel, msgString);
+}
+
+static void sendHook(
+    double timestamp, // in milliseconds
+    const char *receiverName,
+    const HvMessage *const m,
+    void *userData) {
+
+  // only react to messages sent to receivers named "hello"
+  if (!strncmp(receiverName, "hello", 5)) {
+  }
+
+}
+
+/*
+ * RENDER INITIALISATION, LOOP & CLEANUP
+ */
+
+
+// bool initialise_render(int numMatrixChannels, int numAudioChannels,
+// 					   int numMatrixFramesPerPeriod,
+// 					   int numAudioFramesPerPeriod,
+// 					   float matrixSampleRate, float audioSampleRate,
+// 					   void *userData)
+// {
+bool setup(BeagleRTContext *context, void *userData)	{
+
+	/* HEAVY */
+
+	gHeavyContext = hv_bbb_new(context->audioSampleRate);
+
+	gHvInputChannels = hv_getNumInputChannels(gHeavyContext);
+	gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext);
+
+	// srand ( time(NULL) );  	
+
+	rt_printf("Starting Heavy context with %d input channels and %d output channels\n",
+			  gHvInputChannels, gHvOutputChannels);
+
+	if(gHvInputChannels != 0) {
+		gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float));
+		//memset(gHvInputBuffers,0,gHvInputChannels * numAudioFramesPerPeriod * sizeof(float));
+	}
+	if(gHvOutputChannels != 0) {
+		gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float));
+	}
+
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+
+	// Set heavy print hook
+	hv_setPrintHook(gHeavyContext, &printHook);
+	// Set heavy send hook
+	hv_setSendHook(gHeavyContext, sendHook);
+
+	return true;
+}
+
+
+// void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
+// 			uint16_t *matrixIn, uint16_t *matrixOut)
+// {	
+void render(BeagleRTContext *context, void *userData)
+{
+	// use this for thread management
+	// if(gCount == 0) {
+	// } else {
+	// }
+	// gCount++;
+
+	// De-interleave the data
+	if(gHvInputBuffers != NULL) {
+		for(int n = 0; n < context->audioFrames; n++) {
+			for(int ch = 0; ch < gHvInputChannels; ch++) {
+				if(ch >= context->audioChannels+context->analogChannels) {
+					// THESE ARE PARAMETER INPUT 'CHANNELS' USED FOR ROUTING
+					// 'sensor' outputs from routing channels of dac~ are passed through here
+					break;
+				} else {
+					// If more than 2 ADC inputs are used in the pd patch, route the analog inputs
+					// i.e. ADC3->analogIn0 etc. (first two are always audio inputs)
+					if(ch >= context->audioChannels)	{
+						int m = n/2;
+						float mIn = context->analogIn[m*context->analogChannels + (ch-context->audioChannels)];
+						gHvInputBuffers[ch * context->audioFrames + n] = mIn;
+					} else {
+						gHvInputBuffers[ch * context->audioFrames + n] = context->audioIn[n * context->audioChannels + ch];
+					}
+				}
+			}
+		}
+	}
+
+	// replacement for bang~ object
+	//hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b");
+
+	hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames);
+
+	// Interleave the output data
+	if(gHvOutputBuffers != NULL) {
+		for(int n = 0; n < context->audioFrames; n++) {
+
+			for(int ch = 0; ch < gHvOutputChannels; ch++) {
+				if(ch >= context->audioChannels+context->analogChannels) {
+					// THESE ARE SENSOR OUTPUT 'CHANNELS' USED FOR ROUTING
+					// they are the content of the 'sensor output' dac~ channels
+				} else {
+					if(ch >= context->audioChannels)	{
+						int m = n/2;
+						// float mOut = (float)gHvOutputBuffers[ch*numAudioFrames + n];
+						// mOut = constrain(mOut,0.0,1.0);
+						context->analogOut[m * context->analogFrames + (ch-context->audioChannels)] = constrain(gHvOutputBuffers[ch*context->audioFrames + n],0.0,1.0);
+					} else {
+						context->audioOut[n * context->audioChannels + ch] = gHvOutputBuffers[ch * context->audioFrames + n];
+					}
+				}
+			}
+		}
+	}
+
+}
+
+
+void cleanup(BeagleRTContext *context, void *userData)
+{
+
+	hv_bbb_free(gHeavyContext);
+	if(gHvInputBuffers != NULL)
+		free(gHvInputBuffers);
+	if(gHvOutputBuffers != NULL)
+		free(gHvOutputBuffers);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/hvresources/uploader.py	Thu Nov 05 18:58:26 2015 +0000
@@ -0,0 +1,280 @@
+#!/usr/bin/python
+
+# Copyright 2015 Section6. All Rights Reserved.
+
+import argparse
+import getpass
+import json
+import os
+import requests
+import shutil
+import stat
+import tempfile
+import time
+import urlparse
+import zipfile
+import sys
+
+class Colours:
+    purple = "\033[95m"
+    cyan = "\033[96m"
+    dark_cyan = "\033[36m"
+    blue = "\033[94m"
+    green = "\033[92m"
+    yellow = "\033[93m"
+    red = "\033[91m"
+    bold = "\033[1m"
+    underline = "\033[4m"
+    end = "\033[0m"
+
+def __zip_dir(in_dir, zip_path, file_filter=None):
+    zf = zipfile.ZipFile(zip_path, mode="w", compression=zipfile.ZIP_DEFLATED)
+    for subdir, dirs, files in os.walk(in_dir):
+        for file in files:
+            if (file_filter is None) or (len(file_filter) > 0 and file.lower().split(".")[-1] in file_filter):
+                zf.write(
+                    filename=os.path.join(subdir,file),
+                    arcname=os.path.relpath(os.path.join(subdir,file), start=in_dir))
+    return zip_path
+
+def __unzip(zip_path, target_dir):
+    """Unzip a file to a given directory. All destination files are overwritten.
+    """
+    zipfile.ZipFile(zip_path).extractall(target_dir)
+
+def main():
+    parser = argparse.ArgumentParser(
+        description="Compiles a Pure Data file.")
+    parser.add_argument(
+        "input_dir",
+        help="A directory containing _main.pd. The entire directory will be uploaded.")
+    parser.add_argument(
+        "-n", "--name",
+        default="heavy",
+        help="Patch name. If it doesn't exist, the uploader will fail. Make sure that it exists on the Heavy website.")
+    parser.add_argument(
+        "-g", "--gen",
+        nargs="+",
+        default=["c"],
+        help="List of generator outputs. Currently supported generators are 'c' and 'js'.")
+    parser.add_argument(
+        "-b",
+        help="All files will be placed in the output directory, placed in their own subdirectory corresonding to the generator name.",
+        action="count")
+    parser.add_argument(
+        "-o", "--out",
+        nargs="+",
+        default=["./"], # by default
+        help="List of destination directories for retrieved files. Order should be the same as for --gen.")
+    parser.add_argument(
+        "-d", "--domain",
+        default="https://enzienaudio.com",
+        help="Domain. Default is https://enzienaudio.com.")
+    parser.add_argument(
+        "-x",
+        help="Don't save the returned token.",
+        action="count")
+    parser.add_argument(
+        "-z",
+        help="Force the use of a password, regardless of saved token.",
+        action="count")
+    parser.add_argument(
+        "--noverify",
+        help="Don't verify the SSL connection. Generally a bad idea.",
+        action="count")
+    parser.add_argument(
+        "-v", "--verbose",
+        help="Show debugging information.",
+        action="count")
+    args = parser.parse_args()
+
+    domain = args.domain or "https://enzienaudio.com"
+
+    post_data = {}
+
+    # token should be stored in ~/.heavy/token
+    token_path = os.path.expanduser(os.path.join("~/", ".heavy", "token"))
+    if os.path.exists(token_path) and not args.z:
+        with open(token_path, "r") as f:
+            post_data["credentials"] = {
+                "token": f.read()
+            }
+    else:
+        # otherwise, get the username and password
+        post_data["credentials"] = {
+            "username": raw_input("Enter username: "),
+            "password": getpass.getpass("Enter password: ")
+        }
+
+    tick = time.time()
+
+    # make a temporary directory
+    temp_dir = tempfile.mkdtemp(prefix="lroyal-")
+
+    # zip up the pd directory into the temporary directory
+    try:
+        if not os.path.exists(os.path.join(args.input_dir, "_main.pd")):
+            raise Exception("Root Pd directory does not contain a file named _main.pd.")
+        zip_path = __zip_dir(
+            args.input_dir,
+            os.path.join(temp_dir, "archive.zip"),
+            file_filter={"pd"})
+    except Exception as e:
+        print e
+        shutil.rmtree(temp_dir) # clean up the temporary directory
+        return
+
+    post_data["name"] = args.name
+
+    # the outputs to generate (always include c)
+    __SUPPORTED_GENERATOR_SET = {"c", "js"}
+    post_data["gen"] = list(({"c"} | set(args.gen)) & __SUPPORTED_GENERATOR_SET)
+
+    # upload the job, get the response back
+    # NOTE(mhroth): multipart-encoded file can only be sent as a flat dictionary,
+    # but we want to send a json encoded deep dictionary. So we do a bit of a hack.
+    r = requests.post(
+        urlparse.urljoin(domain, "/a/heavy"),
+        data={"json":json.dumps(post_data)},
+        files={"file": (os.path.basename(zip_path), open(zip_path, "rb"), "application/zip")},
+        verify=False if args.noverify else True)
+
+    if r.status_code != requests.codes.ok:
+        shutil.rmtree(temp_dir) # clean up the temporary directory
+        r.raise_for_status() # raise an exception
+
+    # decode the JSON API response
+    r_json = r.json()
+
+    """
+    {
+      "data": {
+        "compileTime": 0.05078411102294922,
+        "id": "mhroth/asdf/Edp2G",
+        "slug": "Edp2G",
+        "index": 3,
+        "links": {
+          "files": {
+            "linkage": [
+              {
+                "id": "mhroth/asdf/Edp2G/c",
+                "type": "file"
+              }
+            ],
+            "self": "https://enzienaudio.com/h/mhroth/asdf/Edp2G/files"
+          },
+          "project": {
+            "linkage": {
+              "id": "mhroth/asdf",
+              "type": "project"
+            },
+            "self": "https://enzienaudio.com/h/mhroth/asdf"
+          },
+          "self": "https://enzienaudio.com/h/mhroth/asdf/Edp2G",
+          "user": {
+            "linkage": {
+              "id": "mhroth",
+              "type": "user"
+            },
+            "self": "https://enzienaudio.com/h/mhroth"
+          }
+        },
+        "type": "job"
+      },
+      "included": [
+        {
+          "filename": "file.c.zip",
+          "generator": "c",
+          "id": "mhroth/asdf/Edp2G/c",
+          "links": {
+            "self": "https://enzienaudio.com/h/mhroth/asdf/Edp2G/c/file.c.zip"
+          },
+          "mime": "application/zip",
+          "type": "file"
+        }
+      ],
+      "warnings": [],
+      "meta": {
+        "token": "11AS0qPRmjTUHEMSovPEvzjodnzB1xaz"
+      }
+    }
+    """
+    reply_json = r.json()
+    if args.verbose:
+        print json.dumps(
+            reply_json,
+            sort_keys=True,
+            indent=2,
+            separators=(",", ": "))
+
+    # update the api token, if present
+    if "token" in reply_json.get("meta",{}) and not args.x:
+        if not os.path.exists(os.path.dirname(token_path)):
+            os.makedirs(os.path.dirname(token_path)) # ensure that the .heavy directory exists
+        with open(token_path, "w") as f:
+            f.write(reply_json["meta"]["token"])
+        os.chmod(token_path, stat.S_IRUSR | stat.S_IWUSR) # force rw------- permissions on the file
+
+    # print any warnings
+    for x in r_json["warnings"]:
+        print "{0}Warning:{1} {2}".format(Colours.yellow, Colours.end, x["detail"])
+
+    # check for errors
+    if len(r_json.get("errors",[])) > 0:
+        shutil.rmtree(temp_dir) # clean up the temporary directory
+        for x in r_json["errors"]:
+            print "{0}Error:{1} {2}".format(Colours.red, Colours.end, x["detail"])
+        sys.exit(1)
+        return
+
+    # retrieve all requested files
+    for i,g in enumerate(args.gen):
+        file_url = __get_file_url_for_generator(reply_json, g)
+        if file_url is not None and (len(args.out) > i or args.b):
+            r = requests.get(
+                file_url,
+                cookies={"token": reply_json["meta"]["token"]},
+                verify=False if args.noverify else True)
+            r.raise_for_status()
+
+            # write the reply to a temporary file
+            c_zip_path = os.path.join(temp_dir, "archive.{0}.zip".format(g))
+            with open(c_zip_path, "wb") as f:
+                f.write(r.content)
+
+            # unzip the files to where they belong
+            if args.b:
+                target_dir = os.path.join(os.path.abspath(os.path.expanduser(args.out[0])), g)
+            else:
+                target_dir = os.path.abspath(os.path.expanduser(args.out[i]))
+            if not os.path.exists(target_dir):
+                os.makedirs(target_dir) # ensure that the output directory exists
+            __unzip(c_zip_path, target_dir)
+
+            print "{0} files placed in {1}".format(g, target_dir)
+        else:
+            print "{0}Warning:{1} {2} files could not be retrieved.".format(
+                Colours.yellow, Colours.end,
+                g)
+
+    # delete the temporary directory
+    shutil.rmtree(temp_dir)
+
+    print "Job URL", reply_json["data"]["links"]["self"]
+    print "Total request time: {0}ms".format(int(1000.0*(time.time()-tick)))
+
+    sys.exit(0)
+
+def __get_file_url_for_generator(json_api, g):
+    """Returns the file link for a specific generator.
+    Returns None if no link could be found.
+    """
+    for i in json_api["included"]:
+        if g == i["generator"]:
+            return i["links"]["self"]
+    return None # by default, return None
+
+
+
+if __name__ == "__main__":
+    main()