diff --git a/l2ork_addons/raspberry_pi/disis_gpio/disis_gpio.c b/l2ork_addons/raspberry_pi/disis_gpio/disis_gpio.c
new file mode 100644
index 0000000000000000000000000000000000000000..74a17243a3066bd8d6bdfa05471de6fd99af49fc
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/disis_gpio/disis_gpio.c
@@ -0,0 +1,149 @@
+/* gpio - Pi gpio pins via /sys/etc */
+/* see http://elinux.org/RPi_Low-level_peripherals */
+
+/* Copyright Ivica Ico Bukic <ico@vt.edu> */
+/* Based on Miller Puckette's example - Copyright Miller Puckette - BSD license */
+/* with changes to make external rely on the gpio executable to sidestep permmission issues */
+
+#include "m_pd.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+static t_class *disis_gpio_class;
+
+//#define FILE_PREFIX "/sys/class/gpio/"
+//#define FILE_EXPORT FILE_PREFIX "export"
+
+typedef struct _disis_gpio
+{
+    t_object x_obj;
+    t_outlet *x_out1;
+    int x_pin;
+    int x_fdvalue;
+    int x_dir;
+} t_disis_gpio;
+
+static void disis_gpio_enable(t_disis_gpio *x, t_float f, t_float dir)
+{
+    char buf[1024];
+    if (f != 0) {
+        if (dir) {
+            sprintf(buf, "gpio export %d out\n", x->x_pin);
+        } else {
+            sprintf(buf, "gpio export %d in\n", x->x_pin);
+        }
+    } else sprintf(buf, "gpio unexport %d\n", x->x_pin);
+    system(buf);
+}
+
+static void disis_gpio_output(t_disis_gpio *x, t_float f)
+{
+    char buf[1024];
+    x->x_dir = f;
+    if (f != 0)
+         sprintf(buf, "gpio -g mode %d out\n",
+            x->x_pin);
+    else sprintf(buf, "gpio -g mode %d in\n",
+        x->x_pin);
+    system(buf);
+}
+
+static void disis_gpio_open(t_disis_gpio *x, t_float f)
+{
+    char buf[1024];
+    sprintf(buf, "/sys/class/gpio/gpio%d/value", x->x_pin);
+    if (f != 0)
+    {
+        if (x->x_fdvalue >= 0)
+            post("disis_gpio: already open");
+        else
+        {
+            x->x_fdvalue = open(buf, O_RDWR);
+            if (x->x_fdvalue < 0)
+                post("%s: %s", buf, strerror(errno));
+        }
+    }
+    else
+    {
+        if (x->x_fdvalue < 0)
+            post("disis_gpio: already closed");
+        else
+        {
+            close(x->x_fdvalue);
+            x->x_fdvalue = -1;
+        }
+    }
+}
+
+static void disis_gpio_float(t_disis_gpio *x, t_float f)
+{
+    char buf[1024];
+    if (x->x_fdvalue < 0)
+        pd_error(x, "disis_gpio: not open");
+    else
+    {
+        sprintf(buf, "%d\n", (f != 0));
+        if (write(x->x_fdvalue, buf, strlen(buf)) < (int)strlen(buf))
+            pd_error(x, "disis_gpio_float: %s", strerror(errno));
+    }
+}
+
+static void disis_gpio_bang(t_disis_gpio *x)
+{
+    char buf[1024];
+    if (x->x_fdvalue < 0)
+        pd_error(x, "disis_gpio: not open");
+    else
+    {
+        int rval = lseek(x->x_fdvalue, 0, 0);
+        if (rval < 0)
+        {
+            pd_error(x, "disis_gpio_bang (seek): %s", strerror(errno));
+            return;
+        }
+        rval = read(x->x_fdvalue, buf, sizeof(buf)-1);
+        if (rval < 0)
+        {
+            pd_error(x, "disis_gpio_bang (read): %s", strerror(errno));
+            return;
+        }
+        buf[rval] = 0;
+        if (sscanf(buf, "%d", &rval) < 1)
+        {
+            pd_error(x, "disis_gpio_bang: couldn't parse string: %s", buf);
+            return;
+        }
+        outlet_float(x->x_out1, rval);
+    }
+}
+
+static void *disis_gpio_new(t_floatarg f)
+{
+    t_disis_gpio *x = (t_disis_gpio *)pd_new(disis_gpio_class);
+    x->x_out1 = outlet_new(&x->x_obj, gensym("float"));
+    x->x_fdvalue = -1;
+    x->x_pin = f;
+    x->x_dir = 0;
+    return (x);
+}
+
+
+void disis_gpio_setup(void)
+{
+    disis_gpio_class = class_new(gensym("disis_gpio"), (t_newmethod)disis_gpio_new,
+        0, sizeof(t_disis_gpio), 0, A_DEFFLOAT, 0);
+    class_addmethod(disis_gpio_class, (t_method)disis_gpio_enable, gensym("enable"), 
+        A_DEFFLOAT, A_DEFFLOAT, 0);
+    class_addmethod(disis_gpio_class, (t_method)disis_gpio_output, gensym("output"), 
+        A_FLOAT, 0);
+    class_addmethod(disis_gpio_class, (t_method)disis_gpio_open, gensym("open"), 
+        A_DEFFLOAT, 0);
+    class_addfloat(disis_gpio_class, disis_gpio_float);
+    class_addbang(disis_gpio_class, disis_gpio_bang);
+}
diff --git a/l2ork_addons/raspberry_pi/disis_gpio/makefile b/l2ork_addons/raspberry_pi/disis_gpio/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d4f66235419c0b29a1595734d45df620a77a9c03
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/disis_gpio/makefile
@@ -0,0 +1,4 @@
+NAME=disis_gpio
+CSYM=$(NAME)
+
+include ../makefile.include
diff --git a/l2ork_addons/raspberry_pi/disis_gpio/test-gpio.pd b/l2ork_addons/raspberry_pi/disis_gpio/test-gpio.pd
new file mode 100644
index 0000000000000000000000000000000000000000..bd2e7c5ceeef7355c83dd99f53170340bc85cbc9
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/disis_gpio/test-gpio.pd
@@ -0,0 +1,25 @@
+#N canvas 187 97 450 300 10;
+#X obj 82 58 gpio 4;
+#X msg 73 21 open 1;
+#X msg 134 22 open 0;
+#X obj 215 24 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 255 24 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X floatatom 94 96 5 0 0 0 - - -;
+#X obj 95 122 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 231 62 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 231 93 metro 1;
+#X obj 175 149 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 175 180 metro 1;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 5 0 6 0;
+#X connect 7 0 8 0;
+#X connect 8 0 0 0;
+#X connect 9 0 10 0;
diff --git a/l2ork_addons/raspberry_pi/disis_spi/disis_spi.c b/l2ork_addons/raspberry_pi/disis_spi/disis_spi.c
new file mode 100644
index 0000000000000000000000000000000000000000..cbdaf5f998f48e15fc8504419c7e3aa25ba23616
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/disis_spi/disis_spi.c
@@ -0,0 +1,251 @@
+/***********************************************************************
+ * This header file contains the mcp3008Spi class definition.
+ * Its main purpose is to communicate with the MCP3008 chip using
+ * the userspace spidev facility.
+ * The class contains four variables:
+ * mode        -> defines the SPI mode used. In our case it is SPI_MODE_0.
+ * bitsPerWord -> defines the bit width of the data transmitted.
+ *        This is normally 8. Experimentation with other values
+ *        didn't work for me
+ * speed       -> Bus speed or SPI clock frequency. According to
+ *                https://projects.drogon.net/understanding-spi-on-the-raspberry-pi/
+ *            It can be only 0.5, 1, 2, 4, 8, 16, 32 MHz.
+ *                Will use 1MHz for now and test it further.
+ * spifd       -> file descriptor for the SPI device
+ *
+ * The class contains two constructors that initialize the above
+ * variables and then open the appropriate spidev device using spiOpen().
+ * The class contains one destructor that automatically closes the spidev
+ * device when object is destroyed by calling spiClose().
+ * The spiWriteRead() function sends the data "data" of length "length"
+ * to the spidevice and at the same time receives data of the same length.
+ * Resulting data is stored in the "data" variable after the function call.
+ * ****************************************************************************/
+#include "m_pd.h"
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/spi/spidev.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+
+static t_class *disis_spi_class;
+
+//#define FILE_PREFIX "/sys/class/gpio/"
+//#define FILE_EXPORT FILE_PREFIX "export"
+
+typedef struct _disis_spi
+{
+    t_object x_obj;
+    t_outlet *x_out1;
+    t_outlet *x_out2;
+    t_symbol *spidev;
+    unsigned char mode;
+    unsigned char bitsPerWord;
+    unsigned int speed;
+    int spifd;
+} t_disis_spi;
+
+static t_disis_spi *disis_spi_new(t_symbol *devspi);
+static int disis_spi_write_read(t_disis_spi *spi, unsigned char *data, int length);
+static void disis_spi_open(t_disis_spi *spi, t_symbol *devspi);
+static int disis_spi_close(t_disis_spi *spi);
+static void disis_spi_free(t_disis_spi *spi);
+
+/**********************************************************
+ * disis_spi_open() :function is called by the constructor.
+ * It is responsible for opening the spidev device
+ * "devspi" and then setting up the spidev interface.
+ * private member variables are used to configure spidev.
+ * They must be set appropriately by constructor before calling
+ * this function.
+ * *********************************************************/
+static void disis_spi_open(t_disis_spi *spi, t_symbol *devspi){
+    int statusVal = 0;
+    if (devspi == &s_)
+      spi->spidev = gensym("/dev/spidev0.0");
+    else
+      spi->spidev = devspi;
+    spi->spifd = open(devspi->s_name, O_RDWR);
+    if(spi->spifd < 0) {
+      pd_error(spi, "could not open SPI device");
+      goto spi_output;
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_WR_MODE, &(spi->mode));
+    if(statusVal < 0){
+      pd_error(spi, "Could not set SPIMode (WR)...ioctl fail");
+      disis_spi_close(spi);
+      goto spi_output;
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_RD_MODE, &(spi->mode));
+    if(statusVal < 0) {
+      pd_error(spi, "Could not set SPIMode (RD)...ioctl fail");
+      disis_spi_close(spi);
+      goto spi_output;
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_WR_BITS_PER_WORD, &(spi->bitsPerWord));
+    if(statusVal < 0) {
+      pd_error(spi, "Could not set SPI bitsPerWord (WR)...ioctl fail");
+      disis_spi_close(spi);
+      goto spi_output;
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_RD_BITS_PER_WORD, &(spi->bitsPerWord));
+    if(statusVal < 0) {
+      pd_error(spi, "Could not set SPI bitsPerWord(RD)...ioctl fail");
+      disis_spi_close(spi);
+      goto spi_output;
+    }  
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_WR_MAX_SPEED_HZ, &(spi->speed));    
+    if(statusVal < 0) {
+      pd_error(spi, "Could not set SPI speed (WR)...ioctl fail");
+      disis_spi_close(spi);
+      goto spi_output;
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_RD_MAX_SPEED_HZ, &(spi->speed));    
+    if(statusVal < 0) {
+      pd_error(spi, "Could not set SPI speed (RD)...ioctl fail");
+      disis_spi_close(spi);
+      goto spi_output;
+    }
+spi_output:
+    outlet_float(spi->x_out2, statusVal);
+}
+
+/***********************************************************
+ * disis_spi_close(): Responsible for closing the spidev interface.
+ * Called in destructor
+ * *********************************************************/
+ 
+static int disis_spi_close(t_disis_spi *spi){
+    int statusVal = -1;
+    if (spi->spifd == -1) {
+      pd_error(spi, "disis_spi: device not open\n");
+      return(-1);
+    }
+    statusVal = close(spi->spifd);
+    if(statusVal < 0) {
+      pd_error(spi, "disis_spi: could not close SPI device");
+      exit(1);
+    }
+    return statusVal;
+}
+
+/********************************************************************
+ * This function frees the object (destructor).
+ * ******************************************************************/
+static void disis_spi_free(t_disis_spi *spi){
+    if (spi->spifd == 0) {
+      disis_spi_close(spi);
+    }
+}
+ 
+/********************************************************************
+ * This function writes data "data" of length "length" to the spidev
+ * device. Data shifted in from the spidev device is saved back into
+ * "data".
+ * ******************************************************************/
+static int disis_spi_write_read(t_disis_spi *spi, unsigned char *data, int length){
+ 
+  struct spi_ioc_transfer spid[length];
+  int i = 0;
+  int retVal = -1; 
+ 
+// one spi transfer for each byte
+ 
+  for (i = 0 ; i < length ; i++){
+ 
+    spid[i].tx_buf        = (unsigned long)(data + i); // transmit from "data"
+    spid[i].rx_buf        = (unsigned long)(data + i); // receive into "data"
+    spid[i].len           = sizeof(*(data + i));
+    spid[i].delay_usecs   = 0;
+    spid[i].speed_hz      = spi->speed;
+    spid[i].bits_per_word = spi->bitsPerWord;
+    spid[i].cs_change     = 0;
+  }
+ 
+  retVal = ioctl(spi->spifd, SPI_IOC_MESSAGE(length), &spid);
+
+  if(retVal < 0){
+    pd_error(spi, "problem transmitting spi data..ioctl");
+  }
+
+  return retVal;
+}
+
+/***********************************************************************
+ * mcp3008 enabled eternal that by default interacts with /dev/spidev0.0 device using
+ * disis_spi_MODE_0 (MODE 0) (defined in linux/spi/spidev.h), speed = 1MHz &
+ * bitsPerWord=8.
+ *
+ * on bang call the spi_write_read function on the a2d object and make sure
+ * that conversion is configured for single ended conversion on CH0
+ * i.e. transmit ->  byte1 = 0b00000001 (start bit)
+ *                   byte2 = 0b1000000  (SGL/DIF = 1, D2=D1=D0=0)
+ *                   byte3 = 0b00000000  (Don't care)
+ *      receive  ->  byte1 = junk
+ *                   byte2 = junk + b8 + b9
+ *                   byte3 = b7 - b0
+ *    
+ * after conversion must merge data[1] and data[2] to get final result
+ *
+ *
+ *
+ * *********************************************************************/
+ 
+static void disis_spi_bang(t_disis_spi *spi)
+{
+  int a2dVal = 0;
+  int a2dChannel = 0;
+  unsigned char data[3];
+
+  data[0] = 1;  //  first byte transmitted -> start bit
+  data[1] = 0b10000000 |( ((a2dChannel & 7) << 4)); // second byte transmitted -> (SGL/DIF = 1, D2=D1=D0=0)
+  data[2] = 0; // third byte transmitted....don't care
+
+  disis_spi_write_read(spi, data, sizeof(data));
+
+  a2dVal = 0;
+  a2dVal = (data[1]<< 8) & 0b1100000000; //merge data[1] & data[2] to get result
+  a2dVal |=  (data[2] & 0xff);
+  fprintf(stderr,"%d\n", a2dVal);
+  outlet_float(spi->x_out1, a2dVal);
+}
+
+/*************************************************
+ * init function. lets user set obj variables
+ * ***********************************************/
+static t_disis_spi *disis_spi_new(t_symbol *devspi){
+    t_disis_spi *spi = (t_disis_spi *)pd_new(disis_spi_class);
+    //fprintf(stderr,"devspi<%s>\n", devspi->s_name); 
+    //t_disis_spi *a2d = disis_spi_new("/dev/spidev0.0", spi_MODE_0, 1000000, 8);
+    spi->x_out1 = outlet_new(&spi->x_obj, gensym("float"));
+    spi->x_out2 = outlet_new(&spi->x_obj, gensym("float"));
+    spi->spidev = devspi;
+    spi->mode = SPI_MODE_0;
+    spi->bitsPerWord = 8;
+    spi->speed = 1000000;
+    spi->spifd = -1;
+ 
+    return(spi);
+}
+
+
+void disis_spi_setup(void)
+{
+    disis_spi_class = class_new(gensym("disis_spi"), (t_newmethod)disis_spi_new,
+        (t_method)disis_spi_free, sizeof(t_disis_spi), 0, A_DEFSYM, 0);
+    class_addmethod(disis_spi_class, (t_method)disis_spi_open, gensym("open"), 
+        A_DEFSYM, 0);
+    class_addmethod(disis_spi_class, (t_method)disis_spi_close, gensym("close"), 
+        0, 0);
+    //class_addfloat(disis_gpio_class, disis_gpio_float); (later do sending data back to the spi)
+    class_addbang(disis_spi_class, disis_spi_bang);
+}
\ No newline at end of file
diff --git a/l2ork_addons/raspberry_pi/disis_spi/makefile b/l2ork_addons/raspberry_pi/disis_spi/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..9bfb9ba3da4d78e45e221c0e51b3d62acaa432a7
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/disis_spi/makefile
@@ -0,0 +1,4 @@
+NAME=disis_spi
+CSYM=$(NAME)
+
+include ../makefile.include
diff --git a/l2ork_addons/raspberry_pi/disis_spi/spi_original.c b/l2ork_addons/raspberry_pi/disis_spi/spi_original.c
new file mode 100644
index 0000000000000000000000000000000000000000..81caae0bf0c9ba49fa54ca21ec1659509826db47
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/disis_spi/spi_original.c
@@ -0,0 +1,224 @@
+/***********************************************************************
+ * This header file contains the mcp3008Spi class definition.
+ * Its main purpose is to communicate with the MCP3008 chip using
+ * the userspace spidev facility.
+ * The class contains four variables:
+ * mode        -> defines the SPI mode used. In our case it is SPI_MODE_0.
+ * bitsPerWord -> defines the bit width of the data transmitted.
+ *        This is normally 8. Experimentation with other values
+ *        didn't work for me
+ * speed       -> Bus speed or SPI clock frequency. According to
+ *                https://projects.drogon.net/understanding-spi-on-the-raspberry-pi/
+ *            It can be only 0.5, 1, 2, 4, 8, 16, 32 MHz.
+ *                Will use 1MHz for now and test it further.
+ * spifd       -> file descriptor for the SPI device
+ *
+ * The class contains two constructors that initialize the above
+ * variables and then open the appropriate spidev device using spiOpen().
+ * The class contains one destructor that automatically closes the spidev
+ * device when object is destroyed by calling spiClose().
+ * The spiWriteRead() function sends the data "data" of length "length"
+ * to the spidevice and at the same time receives data of the same length.
+ * Resulting data is stored in the "data" variable after the function call.
+ * ****************************************************************************/
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/spi/spidev.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+     
+typedef struct _spi {
+    unsigned char mode;
+    unsigned char bitsPerWord;
+    unsigned int speed;
+    int spifd;     
+} t_spi;
+
+t_spi *spi_new(const char *devspi, unsigned char spiMode, unsigned int spiSpeed, unsigned char spibitsPerWord);
+int spi_WriteRead(t_spi *spi, unsigned char *data, int length);
+int spi_Open(t_spi *spi, const char *devspi);
+int spi_Close(t_spi *spi);
+
+//using namespace std;
+/**********************************************************
+ * spiOpen() :function is called by the constructor.
+ * It is responsible for opening the spidev device
+ * "devspi" and then setting up the spidev interface.
+ * private member variables are used to configure spidev.
+ * They must be set appropriately by constructor before calling
+ * this function.
+ * *********************************************************/
+int spi_Open(t_spi *spi, const char *devspi){
+    int statusVal = -1;
+    spi->spifd = open(devspi, O_RDWR);
+    if(spi->spifd < 0) {
+      perror("could not open SPI device");
+      exit(1);
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_WR_MODE, &(spi->mode));
+    if(statusVal < 0){
+      perror("Could not set SPIMode (WR)...ioctl fail");
+      exit(1);
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_RD_MODE, &(spi->mode));
+    if(statusVal < 0) {
+      perror("Could not set SPIMode (RD)...ioctl fail");
+      exit(1);
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_WR_BITS_PER_WORD, &(spi->bitsPerWord));
+    if(statusVal < 0) {
+      perror("Could not set SPI bitsPerWord (WR)...ioctl fail");
+      exit(1);
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_RD_BITS_PER_WORD, &(spi->bitsPerWord));
+    if(statusVal < 0) {
+      perror("Could not set SPI bitsPerWord(RD)...ioctl fail");
+      exit(1);
+    }  
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_WR_MAX_SPEED_HZ, &(spi->speed));    
+    if(statusVal < 0) {
+      perror("Could not set SPI speed (WR)...ioctl fail");
+      exit(1);
+    }
+ 
+    statusVal = ioctl (spi->spifd, SPI_IOC_RD_MAX_SPEED_HZ, &(spi->speed));    
+    if(statusVal < 0) {
+      perror("Could not set SPI speed (RD)...ioctl fail");
+      exit(1);
+    }
+    return statusVal;
+}
+ 
+/***********************************************************
+ * spiClose(): Responsible for closing the spidev interface.
+ * Called in destructor
+ * *********************************************************/
+ 
+int spi_free(t_spi *spi){
+    int statusVal = -1;
+    statusVal = close(spi->spifd);
+        if(statusVal < 0) {
+      perror("Could not close SPI device");
+      exit(1);
+    }
+    return statusVal;
+}
+ 
+/********************************************************************
+ * This function writes data "data" of length "length" to the spidev
+ * device. Data shifted in from the spidev device is saved back into
+ * "data".
+ * ******************************************************************/
+int spi_WriteRead(t_spi *spi, unsigned char *data, int length){
+ 
+  struct spi_ioc_transfer spid[length];
+  int i = 0;
+  int retVal = -1; 
+ 
+// one spi transfer for each byte
+ 
+  for (i = 0 ; i < length ; i++){
+ 
+    spid[i].tx_buf        = (unsigned long)(data + i); // transmit from "data"
+    spid[i].rx_buf        = (unsigned long)(data + i); // receive into "data"
+    spid[i].len           = sizeof(*(data + i));
+    spid[i].delay_usecs   = 0;
+    spid[i].speed_hz      = spi->speed;
+    spid[i].bits_per_word = spi->bitsPerWord;
+    spid[i].cs_change = 0;
+  }
+ 
+  retVal = ioctl(spi->spifd, SPI_IOC_MESSAGE(length), &spid);
+
+  if(retVal < 0){
+    perror("Problem transmitting spi data..ioctl");
+    exit(1);
+  }
+
+  return retVal;
+}
+ 
+/*************************************************
+ * Default constructor. Set member variables to
+ * default values and then call spiOpen()
+ * ***********************************************/
+/* 
+t_spi *spi_new(){
+    spi->mode = SPI_MODE_0 ;
+    spi->bitsPerWord = 8;
+    spi->speed = 1000000;
+    spi->spifd = -1;
+ 
+    spi->spiOpen(std::string("/dev/spidev0.0"));
+ 
+    }
+ */
+/*************************************************
+ * overloaded constructor. let user set member variables to
+ * and then call spiOpen()
+ * ***********************************************/
+t_spi *spi_new(const char *devspi, unsigned char spiMode, unsigned int spiSpeed, unsigned char spibitsPerWord){
+    t_spi *spi = (t_spi *)malloc(sizeof(t_spi)); 
+    spi->mode = spiMode;
+    spi->bitsPerWord = spibitsPerWord;
+    spi->speed = spiSpeed;
+    spi->spifd = -1;
+ 
+    spi_Open(spi, devspi);
+    return spi;
+}
+
+/***********************************************************************
+ * mcp3008SpiTest.cpp. Sample program that tests the mcp3008Spi class.
+ * an mcp3008Spi class object (a2d) is created. the a2d object is instantiated
+ * using the overloaded constructor. which opens the spidev0.0 device with
+ * SPI_MODE_0 (MODE 0) (defined in linux/spi/spidev.h), speed = 1MHz &
+ * bitsPerWord=8.
+ *
+ * call the spiWriteRead function on the a2d object 20 times. Each time make sure
+ * that conversion is configured for single ended conversion on CH0
+ * i.e. transmit ->  byte1 = 0b00000001 (start bit)
+ *                   byte2 = 0b1000000  (SGL/DIF = 1, D2=D1=D0=0)
+ *                   byte3 = 0b00000000  (Don't care)
+ *      receive  ->  byte1 = junk
+ *                   byte2 = junk + b8 + b9
+ *                   byte3 = b7 - b0
+ *    
+ * after conversion must merge data[1] and data[2] to get final result
+ *
+ *
+ *
+ * *********************************************************************/
+//using namespace std;
+ 
+int main(void)
+{
+  t_spi *a2d = spi_new("/dev/spidev0.0", SPI_MODE_0, 1000000, 8);
+  int a2dVal = 0;
+  int a2dChannel = 0;
+  unsigned char data[3];
+
+  while(1)
+  {
+    data[0] = 1;  //  first byte transmitted -> start bit
+    data[1] = 0b10000000 |( ((a2dChannel & 7) << 4)); // second byte transmitted -> (SGL/DIF = 1, D2=D1=D0=0)
+    data[2] = 0; // third byte transmitted....don't care
+
+    spi_WriteRead(a2d, data, sizeof(data));
+
+    a2dVal = 0;
+    a2dVal = (data[1]<< 8) & 0b1100000000; //merge data[1] & data[2] to get result
+    a2dVal |=  (data[2] & 0xff);
+    usleep(10);
+    fprintf(stderr,"%d\n", a2dVal);
+  }
+  return 0;
+}
diff --git a/l2ork_addons/raspberry_pi/gpio/disis_gpio.c b/l2ork_addons/raspberry_pi/gpio/disis_gpio.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ee57174fd42470337a066279793658f4cd95622
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/gpio/disis_gpio.c
@@ -0,0 +1,140 @@
+/* gpio - Pi gpio pins via /sys/etc */
+/* see http://elinux.org/RPi_Low-level_peripherals */
+
+/* Copyright Miller Puckette - BSD license */
+
+#include "m_pd.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+static t_class *gpio_class;
+
+#define FILE_PREFIX "/sys/class/gpio/"
+#define FILE_EXPORT FILE_PREFIX "export"
+
+typedef struct _gpio
+{
+    t_object x_obj;
+    t_outlet *x_out1;
+    int x_pin;
+    int x_fdvalue;
+} t_gpio;
+
+static void gpio_enable(t_gpio *x, t_float f)
+{
+    char buf[1024];
+    if (f != 0)
+         sprintf(buf, "echo %d > /sys/class/gpio/export\n", x->x_pin);
+    else sprintf(buf, "echo %d > /sys/class/gpio/unexport\n", x->x_pin);
+    system(buf);
+}
+
+static void gpio_output(t_gpio *x, t_float f)
+{
+    char buf[1024];
+    if (f != 0)
+         sprintf(buf, "echo out > /sys/class/gpio/gpio%d/direction\n",
+            x->x_pin);
+    else sprintf(buf, "echo in > /sys/class/gpio/gpio%d/direction\n",
+        x->x_pin);
+    system(buf);
+}
+
+static void gpio_open(t_gpio *x, t_float f)
+{
+    char buf[1024];
+    sprintf(buf, "/sys/class/gpio/gpio%d/value", x->x_pin);
+    if (f != 0)
+    {
+        if (x->x_fdvalue >= 0)
+            post("gpio: already open");
+        else
+        {
+            x->x_fdvalue = open(buf, O_RDWR);
+            if (x->x_fdvalue < 0)
+                post("%s: %s", buf, strerror(errno));
+        }
+    }
+    else
+    {
+        if (x->x_fdvalue < 0)
+            post("gpio: already closed");
+        else
+        {
+            close(x->x_fdvalue);
+            x->x_fdvalue = -1;
+        }
+    }
+}
+
+static void gpio_float(t_gpio *x, t_float f)
+{
+    char buf[1024];
+    if (x->x_fdvalue < 0)
+        pd_error(x, "gpio: not open");
+    else
+    {
+        sprintf(buf, "%d\n", (f != 0));
+        if (write(x->x_fdvalue, buf, strlen(buf)) < (int)strlen(buf))
+            pd_error(x, "gpio_float: %s", strerror(errno));
+    }
+}
+
+static void gpio_bang(t_gpio *x)
+{
+    char buf[1024];
+    if (x->x_fdvalue < 0)
+        pd_error(x, "gpio: not open");
+    else
+    {
+        int rval = lseek(x->x_fdvalue, 0, 0);
+        if (rval < 0)
+        {
+            pd_error(x, "gpio_bang (seek): %s", strerror(errno));
+            return;
+        }
+        rval = read(x->x_fdvalue, buf, sizeof(buf)-1);
+        if (rval < 0)
+        {
+            pd_error(x, "gpio_bang (read): %s", strerror(errno));
+            return;
+        }
+        buf[rval] = 0;
+        if (sscanf(buf, "%d", &rval) < 1)
+        {
+            pd_error(x, "gpio_bang: couldn't parse string: %s", buf);
+            return;
+        }
+        outlet_float(x->x_out1, rval);
+    }
+}
+
+static void *gpio_new(t_floatarg f)
+{
+    t_gpio *x = (t_gpio *)pd_new(gpio_class);
+    x->x_out1 = outlet_new(&x->x_obj, gensym("float"));
+    x->x_fdvalue = -1;
+    x->x_pin = f;
+    return (x);
+}
+
+
+void gpio_setup(void)
+{
+    gpio_class = class_new(gensym("gpio"), (t_newmethod)gpio_new,
+        0, sizeof(t_gpio), 0, A_DEFFLOAT, 0);
+    class_addmethod(gpio_class, (t_method)gpio_enable, gensym("enable"), 
+        A_FLOAT, 0);
+    class_addmethod(gpio_class, (t_method)gpio_output, gensym("output"), 
+        A_FLOAT, 0);
+    class_addmethod(gpio_class, (t_method)gpio_open, gensym("open"), 
+        A_FLOAT, 0);
+    class_addfloat(gpio_class, gpio_float);
+    class_addbang(gpio_class, gpio_bang);
+}
diff --git a/l2ork_addons/raspberry_pi/gpio/gpio.c b/l2ork_addons/raspberry_pi/gpio/gpio.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ee57174fd42470337a066279793658f4cd95622
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/gpio/gpio.c
@@ -0,0 +1,140 @@
+/* gpio - Pi gpio pins via /sys/etc */
+/* see http://elinux.org/RPi_Low-level_peripherals */
+
+/* Copyright Miller Puckette - BSD license */
+
+#include "m_pd.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+static t_class *gpio_class;
+
+#define FILE_PREFIX "/sys/class/gpio/"
+#define FILE_EXPORT FILE_PREFIX "export"
+
+typedef struct _gpio
+{
+    t_object x_obj;
+    t_outlet *x_out1;
+    int x_pin;
+    int x_fdvalue;
+} t_gpio;
+
+static void gpio_enable(t_gpio *x, t_float f)
+{
+    char buf[1024];
+    if (f != 0)
+         sprintf(buf, "echo %d > /sys/class/gpio/export\n", x->x_pin);
+    else sprintf(buf, "echo %d > /sys/class/gpio/unexport\n", x->x_pin);
+    system(buf);
+}
+
+static void gpio_output(t_gpio *x, t_float f)
+{
+    char buf[1024];
+    if (f != 0)
+         sprintf(buf, "echo out > /sys/class/gpio/gpio%d/direction\n",
+            x->x_pin);
+    else sprintf(buf, "echo in > /sys/class/gpio/gpio%d/direction\n",
+        x->x_pin);
+    system(buf);
+}
+
+static void gpio_open(t_gpio *x, t_float f)
+{
+    char buf[1024];
+    sprintf(buf, "/sys/class/gpio/gpio%d/value", x->x_pin);
+    if (f != 0)
+    {
+        if (x->x_fdvalue >= 0)
+            post("gpio: already open");
+        else
+        {
+            x->x_fdvalue = open(buf, O_RDWR);
+            if (x->x_fdvalue < 0)
+                post("%s: %s", buf, strerror(errno));
+        }
+    }
+    else
+    {
+        if (x->x_fdvalue < 0)
+            post("gpio: already closed");
+        else
+        {
+            close(x->x_fdvalue);
+            x->x_fdvalue = -1;
+        }
+    }
+}
+
+static void gpio_float(t_gpio *x, t_float f)
+{
+    char buf[1024];
+    if (x->x_fdvalue < 0)
+        pd_error(x, "gpio: not open");
+    else
+    {
+        sprintf(buf, "%d\n", (f != 0));
+        if (write(x->x_fdvalue, buf, strlen(buf)) < (int)strlen(buf))
+            pd_error(x, "gpio_float: %s", strerror(errno));
+    }
+}
+
+static void gpio_bang(t_gpio *x)
+{
+    char buf[1024];
+    if (x->x_fdvalue < 0)
+        pd_error(x, "gpio: not open");
+    else
+    {
+        int rval = lseek(x->x_fdvalue, 0, 0);
+        if (rval < 0)
+        {
+            pd_error(x, "gpio_bang (seek): %s", strerror(errno));
+            return;
+        }
+        rval = read(x->x_fdvalue, buf, sizeof(buf)-1);
+        if (rval < 0)
+        {
+            pd_error(x, "gpio_bang (read): %s", strerror(errno));
+            return;
+        }
+        buf[rval] = 0;
+        if (sscanf(buf, "%d", &rval) < 1)
+        {
+            pd_error(x, "gpio_bang: couldn't parse string: %s", buf);
+            return;
+        }
+        outlet_float(x->x_out1, rval);
+    }
+}
+
+static void *gpio_new(t_floatarg f)
+{
+    t_gpio *x = (t_gpio *)pd_new(gpio_class);
+    x->x_out1 = outlet_new(&x->x_obj, gensym("float"));
+    x->x_fdvalue = -1;
+    x->x_pin = f;
+    return (x);
+}
+
+
+void gpio_setup(void)
+{
+    gpio_class = class_new(gensym("gpio"), (t_newmethod)gpio_new,
+        0, sizeof(t_gpio), 0, A_DEFFLOAT, 0);
+    class_addmethod(gpio_class, (t_method)gpio_enable, gensym("enable"), 
+        A_FLOAT, 0);
+    class_addmethod(gpio_class, (t_method)gpio_output, gensym("output"), 
+        A_FLOAT, 0);
+    class_addmethod(gpio_class, (t_method)gpio_open, gensym("open"), 
+        A_FLOAT, 0);
+    class_addfloat(gpio_class, gpio_float);
+    class_addbang(gpio_class, gpio_bang);
+}
diff --git a/l2ork_addons/raspberry_pi/gpio/gpio.l_arm b/l2ork_addons/raspberry_pi/gpio/gpio.l_arm
new file mode 100755
index 0000000000000000000000000000000000000000..aca8fbd97b9dc1b20eb2ee09ee2f53fac03e37c6
Binary files /dev/null and b/l2ork_addons/raspberry_pi/gpio/gpio.l_arm differ
diff --git a/l2ork_addons/raspberry_pi/gpio/makefile b/l2ork_addons/raspberry_pi/gpio/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..dd3e3df141950357184906fd7a83c9d6f905e4aa
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/gpio/makefile
@@ -0,0 +1,4 @@
+NAME=gpio
+CSYM=$(NAME)
+
+include ../makefile.include
diff --git a/l2ork_addons/raspberry_pi/gpio/test-gpio.pd b/l2ork_addons/raspberry_pi/gpio/test-gpio.pd
new file mode 100644
index 0000000000000000000000000000000000000000..bd2e7c5ceeef7355c83dd99f53170340bc85cbc9
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/gpio/test-gpio.pd
@@ -0,0 +1,25 @@
+#N canvas 187 97 450 300 10;
+#X obj 82 58 gpio 4;
+#X msg 73 21 open 1;
+#X msg 134 22 open 0;
+#X obj 215 24 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 255 24 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X floatatom 94 96 5 0 0 0 - - -;
+#X obj 95 122 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 231 62 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 231 93 metro 1;
+#X obj 175 149 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 175 180 metro 1;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 5 0 6 0;
+#X connect 7 0 8 0;
+#X connect 8 0 0 0;
+#X connect 9 0 10 0;
diff --git a/l2ork_addons/raspberry_pi/makefile.include b/l2ork_addons/raspberry_pi/makefile.include
new file mode 100644
index 0000000000000000000000000000000000000000..23cef8b87c0431d6178f1f1f390af12d5c18a3ae
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/makefile.include
@@ -0,0 +1,134 @@
+current: l_i386 l_ia64
+
+# which OS to compile for
+UNAME := $(shell uname -s)
+ifeq ($(UNAME),Linux)
+  OS_NAME = linux
+  EXTENSION = pd_linux
+  DYLIB_EXTENSION = so
+endif
+ifeq ($(UNAME),Darwin)
+  OS_NAME = darwin
+  EXTENSION = pd_darwin
+  DYLIB_EXTENSION = dylib
+endif
+ifeq (MINGW,$(findstring MINGW,$(UNAME)))
+  OS_NAME = windows
+  EXTENSION = dll
+  DYLIB_EXTENSION = dll
+endif
+ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
+  OS_NAME = windows
+  EXTENSION = dll
+  DYLIB_EXTENSION = dll
+endif
+# which CPU to compile for
+UNAME_MACHINE := $(shell uname -m)
+ifeq ($(UNAME_MACHINE),x86_64)
+  ARCH = l_ia64
+endif
+ifeq ($(UNAME_MACHINE),i386)
+  ARCH = l_i386
+endif
+ifeq ($(UNAME_MACHINE),i686)
+  ARCH = l_i386
+endif
+ifeq ($(UNAME_MACHINE),ppc)
+  ARCH = powerpc
+endif
+
+# ----------------------- Windows -----------------------
+
+pd_nt: $(NAME).dll
+
+.SUFFIXES: .dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+VC="C:\Program Files\Microsoft Visual Studio\Vc98"
+
+PDNTINCLUDE = /I. /I..\pd\src /I..\..\pd\src  /I..\..\..\pd\src /I$(VC)\include
+
+PDNTLDIR = $(VC)\lib
+PDNTLIB = $(PDNTLDIR)\libc.lib \
+	$(PDNTLDIR)\oldnames.lib \
+	$(PDNTLDIR)\kernel32.lib \
+	..\..\bin\pd.lib 
+
+.c.dll:
+	cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+	link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
+
+# ----------------------- LINUX i386 and ia64 -----------------------
+
+l_i386: $(NAME).l_i386
+l_ia64: $(NAME).l_ia64
+
+.SUFFIXES: .l_i386 .l_ia64 .l_arm
+
+LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \
+    -fno-strict-aliasing -Wall -W -Wshadow -Wstrict-prototypes \
+    -Wno-unused -Wno-parentheses -Wno-switch $(CFLAGS)
+
+UNIXINCLUDE =  -I../pd/src -I../../pd/src -I../../../pd/src \
+    -I../../../../pd/src -I../../../../../pd/src
+LINUXINCLUDE =  $(UNIXINCLUDE)
+
+.c.l_i386:
+	$(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -m32 -o $*.o -c $*.c
+	$(CC) -m32 -shared -o $*.l_i386 $*.o -lc -lm
+	strip --strip-unneeded $*.l_i386
+	rm -f $*.o
+	mv $(NAME).l_i386 $(NAME).pd_linux
+
+.c.l_ia64:
+	cc $(LINUXCFLAGS) $(LINUXINCLUDE) -fPIC -o $*.o -c $*.c
+	ld  -shared -o $*.l_ia64 $*.o -lc -lm
+	strip --strip-unneeded $*.l_ia64
+	rm $*.o
+	mv $(NAME).l_ia64 $(NAME).pd_linux
+
+.c.l_arm:
+	cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+	ld  -shared -o $*.l_arm $*.o -lc -lm
+	strip --strip-unneeded $*.l_arm
+	rm $*.o
+	mv $(NAME).l_arm $(NAME).pd_linux
+
+linux:
+ifeq ($(UNAME),Linux)
+ifeq ($(ARCH),l_ia64)
+	make l_ia64
+endif
+ifeq ($(ARCH),l_arm)
+		make l_arm
+endif
+ifeq ($(ARCH),l_i386)
+	make l_i386
+endif
+endif
+
+# ----------------------- Mac OSX -----------------------
+
+d_ppc: $(NAME).d_ppc
+d_fat: $(NAME).d_fat
+
+.SUFFIXES: .d_ppc .d_fat
+
+DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
+    -Wno-unused -Wno-parentheses -Wno-switch
+
+.c.d_ppc:
+	$(CC) $(DARWINCFLAGS) $(UNIXINCLUDE) -o $*.o -c $*.c
+	$(CC) -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o 
+	rm -f $*.o
+
+.c.d_fat:
+	$(CC) -arch i386 -arch ppc $(DARWINCFLAGS) $(UNIXINCLUDE) -o $*.o -c $*.c
+	$(CC) -arch i386 -arch ppc -bundle -undefined suppress -flat_namespace \
+	    -o $*.d_fat $*.o 
+	rm -f $*.o
+
+# ----------------------------------------------------------
+
+clean:
+	rm -f *.o *.pd_* *.d_ppc *.d_fat *.l_i386 *.l_ia64 *.dll
diff --git a/l2ork_addons/raspberry_pi/netreceive_tilde/float_cast.h b/l2ork_addons/raspberry_pi/netreceive_tilde/float_cast.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ebc4bb448ef9d5108687c015aa9063cce6eff5c
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netreceive_tilde/float_cast.h
@@ -0,0 +1,203 @@
+/*
+** Copyright (C) 2001-2003 Erik de Castro Lopo <erikd@mega-nerd.com>
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Version 1.3 */
+
+
+/*============================================================================
+**	On Intel Pentium processors (especially PIII and probably P4), converting
+**	from float to int is very slow. To meet the C specs, the code produced by
+**	most C compilers targeting Pentium needs to change the FPU rounding mode
+**	before the float to int conversion is performed.
+**
+**	Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
+**	is this flushing of the pipeline which is so slow.
+**
+**	Fortunately the ISO C99 specifications define the functions lrint, lrintf,
+**	llrint and llrintf which fix this problem as a side effect.
+**
+**	On Unix-like systems, the configure process should have detected the
+**	presence of these functions. If they weren't found we have to replace them
+**	here with a standard C cast.
+*/
+
+/*
+**	The C99 prototypes for lrint and lrintf are as follows:
+**
+**		long int lrintf (float x) ;
+**		long int lrint  (double x) ;
+*/
+
+// #include "config.h"
+
+/*
+**	The presence of the required functions are detected during the configure
+**	process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
+**	the config.h file.
+*/
+
+#define  HAVE_LRINT_REPLACEMENT 0
+
+#if (HAVE_LRINT && HAVE_LRINTF)
+
+	/*
+	**	These defines enable functionality introduced with the 1999 ISO C
+	**	standard. They must be defined before the inclusion of math.h to
+	**	engage them. If optimisation is enabled, these functions will be
+	**	inlined. With optimisation switched off, you have to link in the
+	**	maths library using -lm.
+	*/
+
+	#define	_ISOC9X_SOURCE	1
+	#define _ISOC99_SOURCE	1
+
+	#define	__USE_ISOC9X	1
+	#define	__USE_ISOC99	1
+
+	#include	<math.h>
+
+#elif (defined (WIN32) || defined (_WIN32))
+
+	#undef   HAVE_LRINT_REPLACEMENT
+	#define  HAVE_LRINT_REPLACEMENT 1
+	#include	<math.h>
+
+	/*
+	**	Win32 doesn't seem to have these functions.
+	**	Therefore implement inline versions of these functions here.
+	*/
+
+	__inline long int
+	lrint (double flt)
+	{	int intgr;
+
+		_asm
+		{	fld flt
+			fistp intgr
+			} ;
+
+		return intgr ;
+	}
+
+	__inline long int
+	lrintf (float flt)
+	{	int intgr;
+
+		_asm
+		{	fld flt
+			fistp intgr
+			} ;
+
+		return intgr ;
+	}
+
+#elif (defined (__MWERKS__) && defined (macintosh))
+
+	/* This MacOS 9 solution was provided by Stephane Letz */
+
+	#undef   HAVE_LRINT_REPLACEMENT
+	#define  HAVE_LRINT_REPLACEMENT 1
+	#include   <math.h>
+
+	#undef	lrint
+	#undef	lrintf
+
+	#define	lrint   double2int
+	#define	lrintf  float2int
+
+	inline int
+	float2int (register float in)
+	{	long res [2] ;
+
+		asm
+		{	fctiw	in,in
+		  	stfd	 in,res
+	  	}
+		return res [1] ;
+	} /* float2int */
+
+	inline int
+	double2int (register double in)
+	{	long res [2] ;
+
+		asm
+		{	fctiw	in,in
+			stfd	 in,res
+	  	}
+		return res [1] ;
+	} /* double2int */
+
+#elif (defined (__MACH__) && defined (__APPLE__))
+
+	/* For Apple MacOSX. */
+
+	#undef   HAVE_LRINT_REPLACEMENT
+	#define  HAVE_LRINT_REPLACEMENT 1
+	#include   <math.h>
+
+	#undef lrint
+	#undef lrintf
+
+	#define lrint	double2int
+	#define lrintf	float2int
+
+	inline static long int
+	float2int (register float in)
+	{	int res [2] ;
+
+		__asm__ __volatile__
+		(	"fctiw	%1, %1\n\t"
+		  	"stfd	%1, %0"
+			: "=m" (res)	/* Output */
+			: "f" (in)		/* Input */
+			: "memory"
+			) ;
+
+		return res [1] ;
+	} /* lrintf */
+
+	inline static long int
+	double2int (register double in)
+	{	int res [2] ;
+
+		__asm__ __volatile__
+		(	"fctiw	%1, %1\n\t"
+		  	"stfd	%1, %0"
+			: "=m" (res)	/* Output */
+			: "f" (in)		/* Input */
+			: "memory"
+			) ;
+
+		return res [1] ;
+	} /* lrint */
+
+#else
+	#ifndef __sgi
+	#warning "Don't have the functions lrint() and lrintf()."
+	#warning "Replacing these functions with a standard C cast."
+	#endif
+
+	#include	<math.h>
+
+	#define	lrint(dbl)		((int) (dbl))
+	#define	lrintf(flt)		((int) (flt))
+
+#endif
+
+
+
diff --git a/l2ork_addons/raspberry_pi/netreceive_tilde/makefile b/l2ork_addons/raspberry_pi/netreceive_tilde/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..be11c9101b3d37fe89ffd933e2f67ca8751f0828
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netreceive_tilde/makefile
@@ -0,0 +1,4 @@
+NAME=netreceive~
+CSYM=netreceive_tilde
+
+include ../makefile.include
diff --git a/l2ork_addons/raspberry_pi/netreceive_tilde/netreceive~.c b/l2ork_addons/raspberry_pi/netreceive_tilde/netreceive~.c
new file mode 100644
index 0000000000000000000000000000000000000000..6ccf27a51558f5e3890d20bfbb7b273e5d35dc64
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netreceive_tilde/netreceive~.c
@@ -0,0 +1,1358 @@
+/* ------------------------ netreceive~ --------------------------------------- */
+/*                                                                              */
+/* Tilde object to receive uncompressed audio data from netsend~.               */
+/* Written by Olaf Matthes <olaf.matthes@gmx.de>.                               */
+/* Based on streamin~ by Guenter Geiger.                                        */
+/* Get source at http://www.akustische-kunst.org/                               */
+/*                                                                              */
+/* This program is free software; you can redistribute it and/or                */
+/* modify it under the terms of the GNU General Public License                  */
+/* as published by the Free Software Foundation; either version 2               */
+/* of the License, or (at your option) any later version.                       */
+/*                                                                              */
+/* See file LICENSE for further informations on licensing terms.                */
+/*                                                                              */
+/* This program is distributed in the hope that it will be useful,              */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of               */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
+/* GNU General Public License for more details.                                 */
+/*                                                                              */
+/* You should have received a copy of the GNU General Public License            */
+/* along with this program; if not, write to the Free Software                  */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  */
+/*                                                                              */
+/* Based on PureData by Miller Puckette and others.                             */
+/*                                                                              */
+/* This project was commissioned by the Society for Arts and Technology [SAT],  */
+/* Montreal, Quebec, Canada, http://www.sat.qc.ca/.                             */
+/*                                                                              */
+/* ---------------------------------------------------------------------------- */
+
+
+#ifdef PD
+#include "m_pd.h"
+#else
+#include "ext.h"
+#include "z_dsp.h"
+#endif
+
+#include "netsend~.h"
+
+#ifdef USE_FAAC
+#include "faad/faad.h"
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#if defined(__linux__) || defined(__apple__)
+#include <sys/socket.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#define SOCKET_ERROR -1
+#else
+#include <winsock.h>
+#endif
+
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#endif
+
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#define DEFAULT_AUDIO_BUFFER_FRAMES 16	/* a small circ. buffer for 16 frames */
+#define DEFAULT_AVERAGE_NUMBER 10		/* number of values we store for average history */
+#define DEFAULT_NETWORK_POLLTIME 1		/* interval in ms for polling for input data (Max/MSP only) */
+#define DEFAULT_QUEUE_LENGTH 3			/* min. number of buffers that can be used reliably on your hardware */
+
+
+#if defined(__linux__) || defined(__apple__)
+#define CLOSESOCKET(fd) close(fd)
+#endif
+#ifdef _WINDOWS
+#define CLOSESOCKET(fd) closesocket(fd)
+#endif
+
+#ifdef PD
+/* these would require to include some headers that are different
+   between pd 0.36 and later, so it's easier to do it like this! */
+EXTERN void sys_rmpollfn(int fd);
+EXTERN void sys_addpollfn(int fd, void* fn, void *ptr);
+#endif
+
+static int netreceive_tilde_sockerror(char *s)
+{
+#ifdef NT
+    int err = WSAGetLastError();
+    if (err == 10054) return 1;
+    else if (err == 10040) post("netsend~: %s: message too long (%d)", s, err);
+    else if (err == 10053) post("netsend~: %s: software caused connection abort (%d)", s, err);
+    else if (err == 10055) post("netsend~: %s: no buffer space available (%d)", s, err);
+    else if (err == 10060) post("netsend~: %s: connection timed out (%d)", s, err);
+    else if (err == 10061) post("netsend~: %s: connection refused (%d)", s, err);
+    else post("netreceive~: %s: %s (%d)", s, strerror(err), err);
+#else
+    int err = errno;
+    post("netreceive~: %s: %s (%d)", s, strerror(err), err);
+#endif
+#ifdef NT
+	if (err == WSAEWOULDBLOCK)
+#endif
+#if defined(__linux__) || defined(__apple__)
+	if (err == EAGAIN)
+#endif
+	{
+		return 1;	/* recoverable error */
+	}
+	return 0;	/* indicate non-recoverable error */
+}
+
+
+static int netreceive_tilde_setsocketoptions(int sockfd)
+{ 
+	int sockopt = 1;
+	if (setsockopt(sockfd, SOL_IP, TCP_NODELAY, (const char*)&sockopt, sizeof(int)) < 0)
+		post("setsockopt NODELAY failed");
+
+	sockopt = 1;    
+	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&sockopt, sizeof(int)) < 0)
+		post("netreceive~: setsockopt REUSEADDR failed");
+	return 0;
+}
+
+
+
+/* ------------------------ netreceive~ ----------------------------- */
+
+
+static t_class *netreceive_tilde_class;
+static t_symbol *ps_format, *ps_channels, *ps_framesize, *ps_overflow, *ps_underflow,
+                *ps_queuesize, *ps_average, *ps_sf_float, *ps_sf_16bit, *ps_sf_8bit, 
+                *ps_sf_mp3, *ps_sf_aac, *ps_sf_unknown, *ps_bitrate, *ps_hostname, *ps_nothing;
+
+
+typedef struct _netreceive_tilde
+{
+#ifdef PD
+	t_object x_obj;
+	t_outlet *x_outlet1;
+	t_outlet *x_outlet2;
+#else
+	t_pxobject x_obj;
+	void *x_outlet1;
+	void *x_outlet2;
+	void *x_connectpoll;
+	void *x_datapoll;
+#endif
+	int x_socket;
+	int x_connectsocket;
+	int x_nconnections;
+	int x_ndrops;
+	int x_tcp;
+	t_symbol *x_hostname;
+
+	/* buffering */
+	int x_framein;
+	int x_frameout;
+	t_frame x_frames[DEFAULT_AUDIO_BUFFER_FRAMES];
+	int x_maxframes;
+	long x_framecount;
+	int x_blocksize;
+	int x_blocksperrecv;
+	int x_blockssincerecv;
+
+	int x_nbytes;
+	int x_counter;
+	int x_average[DEFAULT_AVERAGE_NUMBER];
+	int x_averagecur;
+	int x_underflow;
+	int x_overflow;
+
+#ifdef USE_FAAC
+    faacDecHandle x_faac_decoder;
+    faacDecFrameInfo x_faac_frameInfo;
+    faacDecConfigurationPtr x_faac_config;
+	int x_faac_init;
+	unsigned char x_faac_buf[FAAD_MIN_STREAMSIZE * DEFAULT_AUDIO_CHANNELS];
+	unsigned long x_faac_bytes;
+#endif
+
+	long x_samplerate;
+	int x_noutlets;
+	int x_vecsize;
+	t_int **x_myvec;            /* vector we pass on to the DSP routine */
+} t_netreceive_tilde;
+
+
+
+/* prototypes (as needed) */
+static void netreceive_tilde_kick(t_netreceive_tilde *x);
+
+
+
+#ifdef USE_FAAC
+/* open encoder and set default values */
+static void netreceive_tilde_faac_open(t_netreceive_tilde* x)
+{
+	x->x_faac_decoder = faacDecOpen();
+	x->x_faac_config = faacDecGetCurrentConfiguration(x->x_faac_decoder);
+	x->x_faac_config->defSampleRate = x->x_samplerate;
+	x->x_faac_config->defObjectType = MAIN; // LC;
+	x->x_faac_config->outputFormat = FAAD_FMT_FLOAT;
+	faacDecSetConfiguration(x->x_faac_decoder, x->x_faac_config);
+	x->x_faac_init = 0;
+	x->x_faac_bytes = 0;
+}
+
+static void netreceive_tilde_faac_close(t_netreceive_tilde* x)
+{
+	if (x->x_faac_decoder != NULL)
+		faacDecClose(x->x_faac_decoder);
+	x->x_faac_decoder = NULL;
+	x->x_faac_init = 0;
+}
+
+/* init decoder when we get a new stream */
+static int netreceive_tilde_faac_init(t_netreceive_tilde* x, int frame)
+{
+	unsigned long samplerate;
+    unsigned char channels;
+	long bytes_consumed = 0;
+
+	if ((bytes_consumed = faacDecInit(x->x_faac_decoder, x->x_faac_buf, x->x_faac_bytes, &samplerate, &channels)) < 0)
+	{
+		faacDecConfigurationPtr config;
+		error("netreceive~: faac: initializing decoder library failed");
+		netreceive_tilde_faac_close(x);
+		return -1;
+	}
+	else if (samplerate != (unsigned long)x->x_samplerate)
+	{
+		error("netreceive~: incoming stream has wrong samplerate");
+		netreceive_tilde_faac_close(x);
+		return -1;
+	}
+
+	/* adjust accumulating AAC buffer */
+	memmove(x->x_faac_buf, x->x_faac_buf + bytes_consumed, x->x_faac_bytes - bytes_consumed);
+	x->x_faac_bytes -= bytes_consumed;
+
+	x->x_faac_init = 1;	/* indicate that decoder is ready */
+	return 0;
+}
+
+/* decode AAC using FAAD2 library */
+static int netreceive_tilde_faac_decode(t_netreceive_tilde* x, int frame)
+{
+	unsigned int i, ret;
+	float *sample_buffer;
+
+	/* open decoder, if not yet done */
+	if (x->x_faac_decoder == NULL)
+	{
+		netreceive_tilde_faac_open(x);
+	}
+
+	/* add new AAC data into buffer */
+	memcpy(x->x_faac_buf + x->x_faac_bytes, x->x_frames[frame].data, x->x_frames[frame].tag.framesize);
+	x->x_faac_bytes += x->x_frames[frame].tag.framesize;
+
+	/* in case we have more than FAAD_MIN_STREAMSIZE bytes per channel try decoding */
+	if (x->x_faac_bytes >= (unsigned long)(FAAD_MIN_STREAMSIZE * x->x_frames[frame].tag.channels))
+	{
+		/* init decoder, if not yet done */
+		if (!x->x_faac_init)
+		{
+			ret = netreceive_tilde_faac_init(x, frame);
+			if (ret == -1)
+			{
+				return -1;
+			}
+		}
+
+		/* decode data */
+		memset(&x->x_faac_frameInfo, 0, sizeof(faacDecFrameInfo));
+		sample_buffer = (float *)faacDecDecode(x->x_faac_decoder, &x->x_faac_frameInfo, x->x_faac_buf, x->x_faac_bytes);
+		if (x->x_faac_frameInfo.error != 0)
+		{
+			error("netreceive~: faac: %s", faacDecGetErrorMessage(x->x_faac_frameInfo.error));
+			netreceive_tilde_faac_close(x);
+			return -1;
+		}
+
+		/* adjust accumulating AAC buffer */
+		memmove(x->x_faac_buf, x->x_faac_buf + x->x_faac_frameInfo.bytesconsumed, x->x_faac_bytes - x->x_faac_frameInfo.bytesconsumed);
+		x->x_faac_bytes -= x->x_faac_frameInfo.bytesconsumed;
+
+		/* copy decoded PCM samples back to frame */
+		memcpy(x->x_frames[frame].data, sample_buffer, x->x_faac_frameInfo.samples * sizeof(float));
+
+		/* return number of decoded PCM samples */
+		return x->x_faac_frameInfo.samples * SF_SIZEOF(SF_FLOAT);
+	}
+	else
+	{
+		return 0;	/* indicate we didn't get any new audio data */
+	}
+}
+#endif	/* USE_FAAC */
+
+
+
+
+/* remove all pollfunctions and close socket */
+static void netreceive_tilde_closesocket(t_netreceive_tilde* x)
+{
+#ifdef PD
+	sys_rmpollfn(x->x_socket);
+	outlet_float(x->x_outlet1, 0);
+#else
+	clock_unset(x->x_datapoll);
+	outlet_int(x->x_outlet1, 0);
+#endif
+	CLOSESOCKET(x->x_socket);
+	x->x_socket = -1;
+}
+
+
+
+#ifdef PD
+static void netreceive_tilde_reset(t_netreceive_tilde* x, t_floatarg buffer)
+#else
+static void netreceive_tilde_reset(t_netreceive_tilde* x, double buffer)
+#endif
+{
+	int i;
+	x->x_counter = 0;
+	x->x_nbytes = 0;
+	x->x_framein = 0;
+	x->x_frameout = 0;
+	x->x_blockssincerecv = 0;
+	x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
+#ifdef USE_FAAC
+	x->x_faac_bytes = 0;
+#endif
+
+	for (i = 0; i < DEFAULT_AVERAGE_NUMBER; i++)
+		x->x_average[i] = x->x_maxframes;
+	x->x_averagecur = 0;
+
+	if (buffer == 0.0)	/* set default */
+		x->x_maxframes = DEFAULT_QUEUE_LENGTH;
+	else
+	{
+		buffer = (float)CLIP((float)buffer, 0., 1.);
+		x->x_maxframes = (int)(DEFAULT_AUDIO_BUFFER_FRAMES * buffer);
+		x->x_maxframes = CLIP(x->x_maxframes, 1, DEFAULT_AUDIO_BUFFER_FRAMES - 1);
+		post("netreceive~: set buffer to %g (%d frames)", buffer, x->x_maxframes);
+	}
+	x->x_underflow = 0;
+	x->x_overflow = 0;
+}
+
+
+static void netreceive_tilde_datapoll(t_netreceive_tilde *x)
+{
+#ifndef PD
+	int ret;
+    struct timeval timout;
+    fd_set readset;
+    timout.tv_sec = 0;
+    timout.tv_usec = 0;
+    FD_ZERO(&readset);
+    FD_SET(x->x_socket, &readset);
+
+	ret = select(x->x_socket + 1, &readset, NULL, NULL, &timout);
+    if (ret < 0)
+    {
+    	netreceive_tilde_sockerror("select");
+		return;
+    }
+
+	if (FD_ISSET(x->x_socket, &readset))	/* data available */
+#endif
+	{
+		int ret;
+		int n;
+
+		if (x->x_tcp)
+		{
+			n = x->x_nbytes;
+
+			if (x->x_nbytes == 0)	/* we ate all the samples and need a new header tag */
+			{
+				/* get the new tag */
+				ret = recv(x->x_socket, (char*)&x->x_frames[x->x_framein].tag, sizeof(t_tag), MSG_PEEK);
+				if (ret == 0)	/* disconnect */
+				{
+					post("netreceive~: EOF on socket %d", x->x_socket);
+					netreceive_tilde_closesocket(x);
+					x->x_socket = -1;
+					x->x_counter = 0;
+					return;
+				}
+				if (ret < 0)	/* error */
+				{
+					if (netreceive_tilde_sockerror("recv tag"))
+						goto bail;
+					netreceive_tilde_closesocket(x);
+					x->x_socket = -1;
+					x->x_counter = 0;
+					return;
+				}
+				else if (ret != sizeof(t_tag))
+				{
+					/* incomplete header tag: return and try again later */
+					/* in the hope that more data will be available */
+					return;
+				}
+
+				/* receive header tag */
+				ret = recv(x->x_socket, (char*)&x->x_frames[x->x_framein].tag, sizeof(t_tag), 0);
+
+				/* adjust byte order if neccessarry */
+				if (x->x_frames[x->x_framein].tag.version != SF_BYTE_NATIVE)
+				{
+					x->x_frames[x->x_framein].tag.count = netsend_long(x->x_frames[x->x_framein].tag.count);
+					x->x_frames[x->x_framein].tag.framesize = netsend_long(x->x_frames[x->x_framein].tag.framesize);
+				}
+
+				/* get info from header tag */
+				if (x->x_frames[x->x_framein].tag.channels > x->x_noutlets)
+				{
+					error("netreceive~: incoming stream has too many channels (%d), kicking client", x->x_frames[x->x_framein].tag.channels);
+					netreceive_tilde_kick(x);
+					x->x_socket = -1;
+					x->x_counter = 0;
+					return;
+				}
+				x->x_nbytes = n = x->x_frames[x->x_framein].tag.framesize;
+
+				/* check whether the data packet has the correct count */
+				if ((x->x_framecount != x->x_frames[x->x_framein].tag.count)
+					&& (x->x_frames[x->x_framein].tag.count > 2))
+				{
+					error("netreceive~: we lost %d frames", (int)(x->x_frames[x->x_framein].tag.count - x->x_framecount));
+					post("netreceive~: current package is %d, expected %d", x->x_frames[x->x_framein].tag.count, x->x_framecount);
+				}
+				x->x_framecount = x->x_frames[x->x_framein].tag.count + 1;
+			}
+			else	/* we already have the header tag or some data and need more */
+			{
+				ret = recv(x->x_socket, (char*)x->x_frames[x->x_framein].data + x->x_frames[x->x_framein].tag.framesize - n, n, 0);
+				if (ret > 0)
+				{
+					n -= ret;
+				}
+				else if (ret < 0)	/* error */
+				{
+					if (netreceive_tilde_sockerror("recv data"))
+						goto bail;
+					netreceive_tilde_closesocket(x);
+					x->x_socket = -1;
+					x->x_counter = 0;
+					return;
+				}
+
+				x->x_nbytes = n;
+				if (n == 0)			/* a complete packet is received */
+				{
+#ifdef USE_FAAC     /* decode aac data if format is SF_AAC */
+					if (x->x_frames[x->x_framein].tag.format == SF_AAC)
+					{
+						ret = netreceive_tilde_faac_decode(x, x->x_framein);
+						if (ret == -1)
+						{
+							netreceive_tilde_kick(x);
+							x->x_socket = -1;
+							x->x_counter = 0;
+							return;
+						}
+						else
+						{
+							/* update framesize */
+							x->x_frames[x->x_framein].tag.framesize = ret;
+						}
+					}
+#else
+					if (x->x_frames[x->x_framein].tag.format == SF_AAC)
+					{
+						error("netreceive~: don't know how to decode AAC format");
+						netreceive_tilde_kick(x);
+						x->x_socket = -1;
+						x->x_counter = 0;
+						return;
+					}
+#endif
+
+					x->x_counter++;
+					x->x_framein++;
+					x->x_framein %= DEFAULT_AUDIO_BUFFER_FRAMES;
+
+					/* check for buffer overflow */
+					if (x->x_framein == x->x_frameout)
+					{
+						x->x_overflow++;
+					}
+				}
+			}
+		}
+		else /* UDP */
+		{
+			n = x->x_nbytes;
+
+			if (x->x_nbytes == 0)	/* we ate all the samples and need a new header tag */
+			{
+				/* receive header tag */
+				ret = recv(x->x_socket, (char*)&x->x_frames[x->x_framein].tag, sizeof(t_tag), 0);
+				if (ret <= 0)	/* error */
+				{
+					if (netreceive_tilde_sockerror("recv tag"))
+						goto bail;
+					netreceive_tilde_reset(x, 0);
+					x->x_counter = 0;
+					return;
+				}
+				else if (ret != sizeof(t_tag))
+				{
+					/* incomplete header tag: return and try again later */
+					/* in the hope that more data will be available */
+					error("netreceive~: got incomplete header tag");
+					return;
+				}
+				/* adjust byte order if neccessarry */
+				if (x->x_frames[x->x_framein].tag.version != SF_BYTE_NATIVE)
+				{
+					x->x_frames[x->x_framein].tag.count = netsend_long(x->x_frames[x->x_framein].tag.count);
+					x->x_frames[x->x_framein].tag.framesize = netsend_long(x->x_frames[x->x_framein].tag.framesize);
+				}
+				/* get info from header tag */
+				if (x->x_frames[x->x_framein].tag.channels > x->x_noutlets)
+				{
+					error("netreceive~: incoming stream has too many channels (%d)", x->x_frames[x->x_framein].tag.channels);
+					x->x_counter = 0;
+					return;
+				}
+				x->x_nbytes = n = x->x_frames[x->x_framein].tag.framesize;
+			}
+			else	/* we already have header tag or some data and need more */
+			{
+				ret = recv(x->x_socket, (char*)x->x_frames[x->x_framein].data + x->x_frames[x->x_framein].tag.framesize - n, n, 0);
+				if (ret > 0)
+				{
+					n -= ret;
+				}
+				else if (ret < 0)	/* error */
+				{
+					if (netreceive_tilde_sockerror("recv data"))
+						goto bail;
+					netreceive_tilde_reset(x, 0);
+					x->x_counter = 0;
+					return;
+				}
+
+				x->x_nbytes = n;
+				if (n == 0)			/* a complete packet is received */
+				{
+#ifdef USE_FAAC     /* decode aac data if format is SF_AAC and update framesize */
+					if (x->x_frames[x->x_framein].tag.format == SF_AAC)
+					{
+						ret = netreceive_tilde_faac_decode(x, x->x_framein);
+						if (ret == -1)
+						{
+							return;
+						}
+						else
+						{
+							/* update framesize */
+							x->x_frames[x->x_framein].tag.framesize = ret;
+						}
+					}
+#else
+					if (x->x_frames[x->x_framein].tag.format == SF_AAC)
+					{
+						error("netreceive~: don't know how to decode AAC format");
+						return;
+					}
+#endif
+					x->x_counter++;
+					x->x_framein++;
+					x->x_framein %= DEFAULT_AUDIO_BUFFER_FRAMES;
+
+					/* check for buffer overflow */
+					if (x->x_framein == x->x_frameout)
+					{
+						x->x_overflow++;
+					}
+				}
+			}
+		}
+	}
+bail:
+	;
+#ifndef PD
+	clock_delay(x->x_datapoll, DEFAULT_NETWORK_POLLTIME);
+#endif
+}
+
+
+static void netreceive_tilde_connectpoll(t_netreceive_tilde *x)
+{
+#ifndef PD
+	int ret;
+    struct timeval timout;
+    fd_set readset;
+    timout.tv_sec = 0;
+    timout.tv_usec = 0;
+    FD_ZERO(&readset);
+    FD_SET(x->x_connectsocket, &readset);
+
+	ret = select(x->x_connectsocket + 1, &readset, NULL, NULL, &timout);
+    if (ret < 0)
+    {
+    	netreceive_tilde_sockerror("select");
+		return;
+    }
+
+	if (FD_ISSET(x->x_connectsocket, &readset))	/* pending connection */
+#endif
+	{
+		int sockaddrl = (int)sizeof(struct sockaddr);
+		struct sockaddr_in incomer_address;
+		int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl);
+		if (fd < 0) 
+		{
+			post("netreceive~: accept failed");
+			return;
+		}
+#ifdef O_NONBLOCK
+		fcntl(fd, F_SETFL, O_NONBLOCK);
+#endif
+		if (x->x_socket != -1)
+		{
+			post("netreceive~: new connection");
+			netreceive_tilde_closesocket(x);
+		}
+
+		netreceive_tilde_reset(x, 0);
+		x->x_socket = fd;
+		x->x_nbytes = 0;
+		x->x_hostname = gensym(inet_ntoa(incomer_address.sin_addr));
+#ifdef PD
+		sys_addpollfn(fd, netreceive_tilde_datapoll, x);
+		outlet_float(x->x_outlet1, 1);
+#else
+		clock_delay(x->x_datapoll, 0);
+		outlet_int(x->x_outlet1, 1);
+#endif
+	}
+#ifndef PD
+	clock_delay(x->x_connectpoll, DEFAULT_NETWORK_POLLTIME);
+#endif
+}
+
+
+static int netreceive_tilde_createsocket(t_netreceive_tilde* x, int portno)
+{
+    struct sockaddr_in server;
+    int sockfd;
+    int tcp = x->x_tcp;
+
+     /* create a socket */
+    if (!tcp)
+      sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+    else
+      sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+    if (sockfd < 0)
+    {
+        netreceive_tilde_sockerror("socket");
+        return 0;
+    }
+    server.sin_family = AF_INET;
+    server.sin_addr.s_addr = INADDR_ANY;
+
+    /* assign server port number */
+
+    server.sin_port = htons((u_short)portno);
+    post("listening to port number %d", portno);
+
+    netreceive_tilde_setsocketoptions(sockfd);
+
+    /* name the socket */
+    if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
+	{
+         netreceive_tilde_sockerror("bind");
+         CLOSESOCKET(sockfd);
+         return 0;
+    }
+
+
+    if (!tcp)
+	{
+         x->x_socket = sockfd;
+         x->x_nbytes = 0;
+#ifdef PD
+         sys_addpollfn(sockfd, netreceive_tilde_datapoll, x);
+#else
+		 clock_delay(x->x_datapoll, 0);
+#endif
+    }
+    else
+	{
+         if (listen(sockfd, 5) < 0)
+		 {
+              netreceive_tilde_sockerror("listen");
+              CLOSESOCKET(sockfd);
+			  return 0;
+         }
+         else
+		 {
+              x->x_connectsocket = sockfd;
+			  /* start polling for connection requests */
+#ifdef PD
+              sys_addpollfn(sockfd, netreceive_tilde_connectpoll, x);
+#else
+			  clock_delay(x->x_connectpoll, 0);
+#endif
+         }
+    }
+    return 1;
+}
+
+
+
+/* kick connected client */
+static void netreceive_tilde_kick(t_netreceive_tilde *x)
+{
+	if (x->x_tcp)
+	{
+		if (x->x_socket != -1)
+		{
+			shutdown(x->x_socket, 1);
+			netreceive_tilde_closesocket(x);
+			post("netreceive~: kicked client!");
+		}
+		else error("netreceive~: no client to kick");
+	}
+	else error("netreceive~: kicking clients in UDP mode not possible");
+}
+
+
+#define QUEUESIZE (int)((x->x_framein + DEFAULT_AUDIO_BUFFER_FRAMES - x->x_frameout) % DEFAULT_AUDIO_BUFFER_FRAMES)
+#define BLOCKOFFSET (x->x_blockssincerecv * x->x_vecsize * x->x_frames[x->x_frameout].tag.channels)
+
+static t_int *netreceive_tilde_perform(t_int *w)
+{
+	t_netreceive_tilde *x = (t_netreceive_tilde*) (w[1]);
+	int n = (int)(w[2]);
+	t_float *out[DEFAULT_AUDIO_CHANNELS];
+	const int offset = 3;
+	const int channels = x->x_frames[x->x_frameout].tag.channels;
+	int i = 0;
+
+	for (i = 0; i < x->x_noutlets; i++)
+	{
+		out[i] = (t_float *)(w[offset + i]);
+	}
+
+	if (n != x->x_vecsize)
+	{
+		x->x_vecsize = n;
+		x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
+		x->x_blockssincerecv = 0;
+	}
+
+	/* check whether there is enough data in buffer */
+	if (x->x_counter < x->x_maxframes)
+	{
+		goto bail;
+	}
+
+	/* check for buffer underflow */
+	if (x->x_framein == x->x_frameout)
+	{
+		x->x_underflow++;
+		goto bail;
+	}
+
+
+	/* queue balancing */
+	x->x_average[x->x_averagecur] = QUEUESIZE;
+	if (++x->x_averagecur >= DEFAULT_AVERAGE_NUMBER)
+		x->x_averagecur = 0;
+
+	switch (x->x_frames[x->x_frameout].tag.format)
+	{
+		case SF_FLOAT:
+		{
+			t_float* buf = (t_float *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
+
+			if (x->x_frames[x->x_frameout].tag.version == SF_BYTE_NATIVE)
+			{
+				while (n--)
+				{
+					for (i = 0; i < channels; i++)
+					{     
+						*out[i]++ = *buf++;
+					}
+					for (i = channels; i < x->x_noutlets; i++)
+					{     
+						*out[i]++ = 0.;
+					}
+				}
+			}
+			else	/* swap bytes */
+			{
+				while (n--)
+				{
+					for (i = 0; i < channels; i++)
+					{     
+						*out[i]++ = netsend_float(*buf++);
+					}
+					for (i = channels; i < x->x_noutlets; i++)
+					{     
+						*out[i]++ = 0.;
+					}
+				}
+			}
+			break;
+		}
+		case SF_16BIT:     
+		{
+			short* buf = (short *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
+
+			if (x->x_frames[x->x_frameout].tag.version == SF_BYTE_NATIVE)
+			{
+				while (n--)
+				{
+					for (i = 0; i < channels; i++)
+					{
+						*out[i]++ = (t_float)(*buf++ * 3.051850e-05);
+					}
+					for (i = channels; i < x->x_noutlets; i++)
+					{
+						*out[i]++ = 0.;
+					}
+				}
+			}
+			else /* swap bytes */
+			{
+				while (n--)
+				{
+					for (i = 0; i < channels; i++)
+					{
+						*out[i]++ = (t_float)(netsend_short(*buf++) * 3.051850e-05);
+					}
+					for (i = channels; i < x->x_noutlets; i++)
+					{
+						*out[i]++ = 0.;
+					}
+				}
+			}
+			break;
+		}
+		case SF_8BIT:     
+		{
+			unsigned char* buf = (char *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
+
+			while (n--)
+			{
+				for (i = 0; i < channels; i++)
+				{ 
+					*out[i]++ = (t_float)((0.0078125 * (*buf++)) - 1.0);
+				}
+				for (i = channels; i < x->x_noutlets; i++)
+				{
+					*out[i]++ = 0.;
+				}
+			}
+			break;
+		}
+		case SF_MP3:     
+		{
+			post("netreceive~: mp3 format not supported");
+			if (x->x_tcp)
+				netreceive_tilde_kick(x);
+			break;
+		}
+		case SF_AAC:     
+		{
+#ifdef USE_FAAC
+			t_float* buf = (t_float *)x->x_frames[x->x_frameout].data + BLOCKOFFSET;
+
+			while (n--)
+			{
+				for (i = 0; i < channels; i++)
+				{     
+					*out[i]++ = (t_float)(*buf++);
+				}
+				for (i = channels; i < x->x_noutlets; i++)
+				{     
+					*out[i]++ = 0.;
+				}
+			}
+			break;
+#else
+			post("netreceive~: aac format not supported");
+			if (x->x_tcp)
+				netreceive_tilde_kick(x);
+#endif
+			break;
+		}
+		default:
+			post("netreceive~: unknown format (%d)",x->x_frames[x->x_frameout].tag.format);
+			if (x->x_tcp)
+				netreceive_tilde_kick(x);
+			break;
+	}
+
+	if (!(x->x_blockssincerecv < x->x_blocksperrecv - 1))
+	{
+		x->x_blockssincerecv = 0;
+		x->x_frameout++;
+		x->x_frameout %= DEFAULT_AUDIO_BUFFER_FRAMES;
+	}
+	else
+	{
+		x->x_blockssincerecv++;
+	}
+
+	return (w + offset + x->x_noutlets);
+
+bail:
+	/* set output to zero */
+	while (n--)
+	{
+		for (i = 0; i < x->x_noutlets; i++)
+		{
+			*(out[i]++) = 0.;
+		}
+	}
+	return (w + offset + x->x_noutlets);
+}
+
+
+
+static void netreceive_tilde_dsp(t_netreceive_tilde *x, t_signal **sp)
+{
+	int i;
+
+	x->x_myvec[0] = (t_int*)x;
+	x->x_myvec[1] = (t_int*)sp[0]->s_n;
+
+	x->x_samplerate = (long)sp[0]->s_sr;
+
+	if (DEFAULT_AUDIO_BUFFER_SIZE % sp[0]->s_n)
+	{
+		error("netsend~: signal vector size too large (needs to be even divisor of %d)", DEFAULT_AUDIO_BUFFER_SIZE);
+	}
+	else
+	{
+#ifdef PD
+		for (i = 0; i < x->x_noutlets; i++)
+		{
+			x->x_myvec[2 + i] = (t_int*)sp[i + 1]->s_vec;
+		}
+		dsp_addv(netreceive_tilde_perform, x->x_noutlets + 2, (t_int*)x->x_myvec);
+#else
+		for (i = 0; i < x->x_noutlets; i++)
+		{
+			x->x_myvec[2 + i] = (t_int*)sp[i]->s_vec;
+		}
+		dsp_addv(netreceive_tilde_perform, x->x_noutlets + 2, (void **)x->x_myvec);
+#endif	/* PD */
+	}
+}
+
+
+/* send stream info when banged */
+static void netreceive_tilde_bang(t_netreceive_tilde *x)
+{
+	t_atom list[2];
+	t_symbol *sf_format;
+	t_float bitrate;
+	int i, avg = 0;
+	for (i = 0; i < DEFAULT_AVERAGE_NUMBER; i++)
+		avg += x->x_average[i];
+
+	bitrate = (t_float)((SF_SIZEOF(x->x_frames[x->x_frameout].tag.format) * x->x_samplerate * 8 * x->x_frames[x->x_frameout].tag.channels) / 1000.);
+
+	switch (x->x_frames[x->x_frameout].tag.format)
+	{
+		case SF_FLOAT:
+		{
+			sf_format = ps_sf_float;
+			break;
+		}
+		case SF_16BIT:
+		{
+			sf_format = ps_sf_16bit;
+			break;
+		}
+		case SF_8BIT:
+		{
+			sf_format = ps_sf_8bit;
+			break;
+		}
+		case SF_MP3:
+		{
+			sf_format = ps_sf_mp3;
+			break;
+		}
+		case SF_AAC:
+		{
+			sf_format = ps_sf_aac;
+			break;
+		}
+		default:
+		{
+			sf_format = ps_sf_unknown;
+			break;
+		}
+	}
+
+#ifdef PD
+	/* --- stream information (t_tag) --- */
+	/* audio format */
+	SETSYMBOL(list, (t_symbol *)sf_format);
+	outlet_anything(x->x_outlet2, ps_format, 1, list);
+
+	/* channels */
+	SETFLOAT(list, (t_float)x->x_frames[x->x_frameout].tag.channels);
+	outlet_anything(x->x_outlet2, ps_channels, 1, list);
+
+	/* framesize */
+	SETFLOAT(list, (t_float)x->x_frames[x->x_frameout].tag.framesize);
+	outlet_anything(x->x_outlet2, ps_framesize, 1, list);
+
+	/* bitrate */
+	SETFLOAT(list, (t_float)bitrate);
+	outlet_anything(x->x_outlet2, ps_bitrate, 1, list);
+
+	/* --- internal info (buffer and network) --- */
+	/* overflow */
+	SETFLOAT(list, (t_float)x->x_overflow);
+	outlet_anything(x->x_outlet2, ps_overflow, 1, list);
+
+	/* underflow */
+	SETFLOAT(list, (t_float)x->x_underflow);
+	outlet_anything(x->x_outlet2, ps_underflow, 1, list);
+
+	/* queuesize */
+	SETFLOAT(list, (t_float)QUEUESIZE);
+	outlet_anything(x->x_outlet2, ps_queuesize, 1, list);
+
+	/* average queuesize */
+	SETFLOAT(list, (t_float)((t_float)avg / (t_float)DEFAULT_AVERAGE_NUMBER));
+	outlet_anything(x->x_outlet2, ps_average, 1, list);
+
+	if (x->x_tcp)
+	{
+		/* IP address */
+		SETSYMBOL(list, (t_symbol *)x->x_hostname);
+		outlet_anything(x->x_outlet2, ps_hostname, 1, list);
+	}
+#else
+	/* --- stream information (t_tag) --- */
+	/* audio format */
+	SETSYM(list, ps_format);
+	SETSYM(list + 1, (t_symbol *)sf_format);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* channels */
+	SETSYM(list, ps_channels);
+	SETLONG(list + 1, (int)x->x_frames[x->x_frameout].tag.channels);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* framesize */
+	SETSYM(list, ps_framesize);
+	SETLONG(list + 1, (int)x->x_frames[x->x_frameout].tag.framesize);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* bitrate */
+	SETSYM(list, ps_bitrate);
+	SETFLOAT(list + 1, (t_float)bitrate);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* --- internal info (buffer and network) --- */
+	/* overflow */
+	SETSYM(list, ps_overflow);
+	SETLONG(list + 1, (int)x->x_overflow);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* underflow */
+	SETSYM(list, ps_underflow);
+	SETLONG(list + 1, (int)x->x_underflow);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* queuesize */
+	SETSYM(list, ps_queuesize);
+	SETLONG(list + 1, (int)QUEUESIZE);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* average queuesize */
+	SETSYM(list, ps_average);
+	SETFLOAT(list + 1, (t_float)((t_float)avg / (t_float)DEFAULT_AVERAGE_NUMBER));
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	if (x->x_tcp)
+	{
+		/* IP address */
+		SETSYM(list, (t_symbol *)ps_hostname);
+		SETSYM(list + 1, x->x_hostname);
+		outlet_list(x->x_outlet2, NULL, 2, list);
+	}
+#endif
+}
+
+
+
+static void netreceive_tilde_print(t_netreceive_tilde* x)
+{
+	int i, avg = 0;
+	for (i = 0; i < DEFAULT_AVERAGE_NUMBER; i++)
+		avg += x->x_average[i];
+	post("netreceive~: last size = %d, avg size = %g, %d underflows, %d overflows", QUEUESIZE, (float)((float)avg / (float)DEFAULT_AVERAGE_NUMBER), x->x_underflow, x->x_overflow);
+	post("netreceive~: channels = %d, framesize = %d, packets = %d", x->x_frames[x->x_framein].tag.channels, x->x_frames[x->x_framein].tag.framesize, x->x_counter);
+}
+
+
+
+#ifdef PD
+static void *netreceive_tilde_new(t_floatarg fportno, t_floatarg outlets, t_floatarg prot)
+#else
+static void *netreceive_tilde_new(long fportno, long outlets, long prot)
+#endif
+{
+	t_netreceive_tilde *x;
+	int i;
+
+	if (fportno == 0) fportno = DEFAULT_PORT;
+
+#ifdef PD
+	x = (t_netreceive_tilde *)pd_new(netreceive_tilde_class);
+    if (x)
+    { 
+        for (i = sizeof(t_object); i < (int)sizeof(t_netreceive_tilde); i++)  
+                ((char *)x)[i] = 0; 
+	}
+
+	x->x_noutlets = CLIP((int)outlets, 1, DEFAULT_AUDIO_CHANNELS);
+	for (i = 0; i < x->x_noutlets; i++)
+		outlet_new(&x->x_obj, &s_signal);
+	if (!prot)
+		x->x_outlet1 = outlet_new(&x->x_obj, &s_anything);	/* outlet for connection state (TCP/IP) */
+	x->x_outlet2 = outlet_new(&x->x_obj, &s_anything);
+#else
+	x = (t_netreceive_tilde *)newobject(netreceive_tilde_class);
+    if (x)
+    { 
+        for (i = sizeof(t_pxobject); i < (int)sizeof(t_netreceive_tilde); i++)  
+                ((char *)x)[i] = 0; 
+	}
+
+	dsp_setup((t_pxobject *)x, 0);	/* no signal inlets */
+	x->x_noutlets = CLIP((int)outlets, 1, DEFAULT_AUDIO_CHANNELS);
+	x->x_outlet2 = listout(x);	/* outlet for info list */
+	if (!prot)
+		x->x_outlet1 = listout(x);	/* outlet for connection state (TCP/IP) */
+	for (i = 0 ; i < x->x_noutlets; i++)
+		outlet_new(x, "signal");
+	x->x_connectpoll = clock_new(x, (method)netreceive_tilde_connectpoll);
+	x->x_datapoll = clock_new(x, (method)netreceive_tilde_datapoll);
+#endif
+
+	x->x_myvec = (t_int **)t_getbytes(sizeof(t_int *) * (x->x_noutlets + 3));
+	if (!x->x_myvec)
+	{
+		error("netreceive~: out of memory");
+		return NULL;
+	}
+
+#ifdef USE_FAAC
+	x->x_faac_decoder = NULL;
+	x->x_faac_init = 0;
+#endif
+
+	x->x_connectsocket = -1;
+	x->x_socket = -1;
+	x->x_tcp = 1;
+	x->x_nconnections = 0;
+	x->x_ndrops = 0;
+	x->x_underflow = 0;
+	x->x_overflow = 0;
+	x->x_hostname = ps_nothing;
+
+	for (i = 0; i < DEFAULT_AUDIO_BUFFER_FRAMES; i++)
+	{
+		x->x_frames[i].data = (char *)t_getbytes(DEFAULT_AUDIO_BUFFER_SIZE * x->x_noutlets * sizeof(t_float));
+	}
+	x->x_framein = 0;
+	x->x_frameout = 0;
+	x->x_maxframes = DEFAULT_QUEUE_LENGTH;
+	x->x_vecsize = 64;	/* we'll update this later */
+	x->x_blocksize = DEFAULT_AUDIO_BUFFER_SIZE;	/* LATER make this dynamic */
+	x->x_blockssincerecv = 0;
+	x->x_blocksperrecv = x->x_blocksize / x->x_vecsize;
+
+	if (prot)
+		x->x_tcp = 0;
+
+	if (!netreceive_tilde_createsocket(x, (int)fportno))
+	{
+		error("netreceive~: failed to create listening socket");
+		return (NULL);
+	}
+
+	return (x);
+}
+
+
+
+static void netreceive_tilde_free(t_netreceive_tilde *x)
+{
+	int i;
+
+	if (x->x_connectsocket != -1)
+	{
+#ifdef PD
+		sys_rmpollfn(x->x_connectsocket);
+#else
+		clock_unset(x->x_connectpoll);
+#endif
+		CLOSESOCKET(x->x_connectsocket);
+	}
+	if (x->x_socket != -1)
+	{
+#ifdef PD
+		sys_rmpollfn(x->x_socket);
+#else
+		clock_unset(x->x_datapoll);
+#endif
+		CLOSESOCKET(x->x_socket);
+	}
+
+#ifndef PD
+	dsp_free((t_pxobject *)x);	/* free the object */
+	clock_free(x->x_connectpoll);
+	clock_free(x->x_datapoll);
+#endif
+
+#ifdef USE_FAAC
+	netreceive_tilde_faac_close(x);
+#endif
+
+	/* free memory */
+	t_freebytes(x->x_myvec, sizeof(t_int *) * (x->x_noutlets + 3));
+	for (i = 0; i < DEFAULT_AUDIO_BUFFER_FRAMES; i++)
+	{
+		 t_freebytes(x->x_frames[i].data, DEFAULT_AUDIO_BUFFER_SIZE * x->x_noutlets * sizeof(t_float));
+	}
+}
+
+
+
+#ifdef PD
+void netreceive_tilde_setup(void)
+{
+	netreceive_tilde_class = class_new(gensym("netreceive~"), 
+		(t_newmethod) netreceive_tilde_new, (t_method) netreceive_tilde_free,
+		sizeof(t_netreceive_tilde),  0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+
+	class_addmethod(netreceive_tilde_class, nullfn, gensym("signal"), 0);
+	class_addbang(netreceive_tilde_class, (t_method)netreceive_tilde_bang);
+	class_addmethod(netreceive_tilde_class, (t_method)netreceive_tilde_dsp, gensym("dsp"), 0);
+	class_addmethod(netreceive_tilde_class, (t_method)netreceive_tilde_print, gensym("print"), 0);
+	class_addmethod(netreceive_tilde_class, (t_method)netreceive_tilde_kick, gensym("kick"), 0);
+	class_addmethod(netreceive_tilde_class, (t_method)netreceive_tilde_reset, gensym("reset"), A_DEFFLOAT, 0);
+	class_addmethod(netreceive_tilde_class, (t_method)netreceive_tilde_reset, gensym("buffer"), A_DEFFLOAT, 0);
+	class_sethelpsymbol(netreceive_tilde_class, gensym("netsend~"));
+	post("netreceive~ v%s, (c) 2004 Olaf Matthes", VERSION);
+
+	ps_format = gensym("format");
+	ps_channels = gensym("channels");
+	ps_framesize = gensym("framesize");
+	ps_bitrate = gensym("bitrate");
+	ps_overflow = gensym("overflow");
+	ps_underflow = gensym("underflow");
+	ps_queuesize = gensym("queuesize");
+	ps_average = gensym("average");
+	ps_hostname = gensym("ipaddr");
+	ps_sf_float = gensym("_float_");
+	ps_sf_16bit = gensym("_16bit_");
+	ps_sf_8bit = gensym("_8bit_");
+	ps_sf_mp3 = gensym("_mp3_");
+	ps_sf_aac = gensym("_aac_");
+	ps_sf_unknown = gensym("_unknown_");
+	ps_nothing = gensym("");
+}
+
+#else
+
+void netreceive_tilde_assist(t_netreceive_tilde *x, void *b, long m, long a, char *s)
+{
+	switch (m)
+	{
+		case 1: /* inlet */
+			sprintf(s, "(Anything) Control Messages");
+			break;
+		case 2: /* outlets */
+			sprintf(s, "(Signal) Audio Channel %d", (int)(a + 1));
+			break;
+		break;
+	}
+
+}
+
+void main()
+{
+#ifdef _WINDOWS
+    short version = MAKEWORD(2, 0);
+    WSADATA nobby;
+#endif	/* _WINDOWS */
+
+	setup((t_messlist **)&netreceive_tilde_class, (method)netreceive_tilde_new, (method)netreceive_tilde_free, 
+		  (short)sizeof(t_netreceive_tilde), 0L, A_DEFLONG, A_DEFLONG, A_DEFLONG, 0);
+	addmess((method)netreceive_tilde_dsp, "dsp", A_CANT, 0);
+	addmess((method)netreceive_tilde_assist, "assist", A_CANT, 0);
+	addmess((method)netreceive_tilde_print, "print", 0);
+	addmess((method)netreceive_tilde_kick, "kick", 0);
+	addmess((method)netreceive_tilde_reset, "reset", A_DEFFLOAT, 0);
+	addmess((method)netreceive_tilde_reset, "buffer", A_DEFFLOAT, 0);
+	addbang((method)netreceive_tilde_bang);
+	dsp_initclass();
+	finder_addclass("System", "netreceive~");
+	post("netreceive~ v%s, © 2004 Olaf Matthes", VERSION);
+
+	ps_format = gensym("format");
+	ps_channels = gensym("channels");
+	ps_framesize = gensym("framesize");
+	ps_bitrate = gensym("bitrate");
+	ps_overflow = gensym("overflow");
+	ps_underflow = gensym("underflow");
+	ps_queuesize = gensym("queuesize");
+	ps_average = gensym("average");
+	ps_hostname = gensym("ipaddr");
+	ps_sf_float = gensym("_float_");
+	ps_sf_16bit = gensym("_16bit_");
+	ps_sf_8bit = gensym("_8bit_");
+	ps_sf_mp3 = gensym("_mp3_");
+	ps_sf_aac = gensym("_aac_");
+	ps_sf_unknown = gensym("_unknown_");
+	ps_nothing = gensym("");
+
+#ifdef _WINDOWS
+    if (WSAStartup(version, &nobby)) error("netreceive~: WSAstartup failed");
+#endif	/* _WINDOWS */
+}
+#endif	/* PD */
diff --git a/l2ork_addons/raspberry_pi/netreceive_tilde/netsend~.h b/l2ork_addons/raspberry_pi/netreceive_tilde/netsend~.h
new file mode 100644
index 0000000000000000000000000000000000000000..874b63f25b48ea82ee4e7e6d38d9ff67db4e4425
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netreceive_tilde/netsend~.h
@@ -0,0 +1,154 @@
+/* ------------------------ netsend~ ------------------------------------------ */
+/*                                                                              */
+/* Tilde object to send uncompressed audio data to netreceive~.                 */
+/* Written by Olaf Matthes <olaf.matthes@gmx.de>.                               */
+/* Based on streamout~ by Guenter Geiger.                                       */
+/* Get source at http://www.akustische-kunst.org/                               */
+/*                                                                              */
+/* This program is free software; you can redistribute it and/or                */
+/* modify it under the terms of the GNU General Public License                  */
+/* as published by the Free Software Foundation; either version 2               */
+/* of the License, or (at your option) any later version.                       */
+/*                                                                              */
+/* See file LICENSE for further informations on licensing terms.                */
+/*                                                                              */
+/* This program is distributed in the hope that it will be useful,              */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of               */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
+/* GNU General Public License for more details.                                 */
+/*                                                                              */
+/* You should have received a copy of the GNU General Public License            */
+/* along with this program; if not, write to the Free Software                  */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  */
+/*                                                                              */
+/* Based on PureData by Miller Puckette and others.                             */
+/*                                                                              */
+/* This project was commissioned by the Society for Arts and Technology [SAT],  */
+/* Montreal, Quebec, Canada, http://www.sat.qc.ca/.                             */
+/*                                                                              */
+/* ---------------------------------------------------------------------------- */
+
+
+/* This file is based on and inspired by stream.h (C) Guenter Geiger 1999.   */
+/* Some enhancements have been made with the goal of keeping compatibility   */
+/* between the stream formats of streamout~/in~ and netsend~/receive~.       */
+
+#define VERSION "1.0alpha11"
+
+#define DEFAULT_AUDIO_CHANNELS 32	    /* nax. number of audio channels we support */
+#define DEFAULT_AUDIO_BUFFER_SIZE 1024	/* number of samples in one audio block */
+#define DEFAULT_UDP_PACKT_SIZE 8192		/* number of bytes we send in one UDP datagram (OS X only) */
+#define DEFAULT_PORT 8000               /* default network port number */
+
+#ifdef _WINDOWS
+#ifndef HAVE_INT32_T
+typedef int int32_t;
+#define HAVE_INT32_T
+#endif
+#ifndef HAVE_INT16_T
+typedef short int16_t;
+#define HAVE_INT16_T
+#endif
+#ifndef HAVE_U_INT32_T
+typedef unsigned int u_int32_t;
+#define HAVE_U_INT32_T
+#endif
+#ifndef HAVE_U_INT16_T
+typedef unsigned short u_int16_t;
+#define HAVE_U_INT16_T
+#endif
+#endif
+
+#ifndef CLIP
+#define CLIP(a, lo, hi) ( (a)>(lo)?( (a)<(hi)?(a):(hi) ):(lo) )
+#endif
+
+
+/* swap 32bit t_float. Is there a better way to do that???? */
+#ifdef _WINDOWS
+__inline static float netsend_float(float f)
+#else
+inline static float netsend_float(float f)
+#endif
+{
+    union
+    {
+        float f;
+        unsigned char b[4];
+    } dat1, dat2;
+    
+    dat1.f = f;
+    dat2.b[0] = dat1.b[3];
+    dat2.b[1] = dat1.b[2];
+    dat2.b[2] = dat1.b[1];
+    dat2.b[3] = dat1.b[0];
+    return dat2.f;
+}
+
+/* swap 32bit long int */
+#ifdef _WINDOWS
+__inline static long netsend_long(long n)
+#else
+inline static long netsend_long(long n)
+#endif
+{
+    return (((n & 0xff) << 24) | ((n & 0xff00) << 8) |
+    	((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24));
+}
+
+/* swap 16bit short int */
+#ifdef _WINDOWS
+__inline static long netsend_short(long n)
+#else
+inline static short netsend_short(short n)
+#endif
+{
+    return (((n & 0xff) << 8) | ((n & 0xff00) >> 8));
+}
+
+
+/* format specific stuff */
+
+#define SF_FLOAT  1
+#define SF_DOUBLE 2		/* not implemented */
+#define SF_8BIT   10
+#define SF_16BIT  11
+#define SF_32BIT  12	/* not implemented */
+#define SF_ALAW   20	/* not implemented */
+#define SF_MP3    30    /* not implemented */
+#define SF_AAC    31    /* AAC encoding using FAAC */
+#define SF_VORBIS 40	/* not implemented */
+#define SF_FLAC   50	/* not implemented */
+
+#define SF_SIZEOF(a) (a == SF_FLOAT ? sizeof(t_float) : \
+                     a == SF_16BIT ? sizeof(short) : 1)
+
+
+/* version / byte-endian specific stuff */
+
+#define SF_BYTE_LE 1		/* little endian */
+#define SF_BYTE_BE 2		/* big endian */
+
+#if defined(_WINDOWS) || defined(__linux__) || defined(IRIX)
+#define SF_BYTE_NATIVE SF_BYTE_LE
+#else /* must be  __APPLE__ */
+#define SF_BYTE_NATIVE SF_BYTE_BE
+#endif
+
+
+typedef struct _tag {      /* size (bytes) */
+     char version;         /*    1         */
+     char format;          /*    1         */
+     long count;           /*    4         */
+     char channels;        /*    1         */
+     long framesize;       /*    4         */
+     char  extension[5];   /*    5         */
+} t_tag;                   /*--------------*/
+                           /*   16         */
+
+
+typedef struct _frame {
+     t_tag  tag;
+     char  *data;
+} t_frame;
+
diff --git a/l2ork_addons/raspberry_pi/netreceive_tilde/test-netsend~.pd b/l2ork_addons/raspberry_pi/netreceive_tilde/test-netsend~.pd
new file mode 100644
index 0000000000000000000000000000000000000000..d3d9cbf5f99a069fe7bc787d5560a95ef58c8131
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netreceive_tilde/test-netsend~.pd
@@ -0,0 +1,72 @@
+#N canvas 291 209 642 596 10;
+#X obj 18 178 netreceive~ 8008 4;
+#X obj 19 514 netsend~ 4;
+#X obj 18 221 dac~ 1;
+#X obj 68 221 dac~ 2;
+#X obj 121 221 dac~ 3;
+#X obj 175 222 dac~ 4;
+#X obj 74 480 osc~ 440;
+#X obj 145 481 osc~ 880;
+#X obj 214 480 osc~ 990;
+#X obj 281 481 osc~ 220;
+#X text 245 515 sends 4 dsp-channels to localhost:8008;
+#X msg 62 325 disconnect;
+#X msg 76 350 format float;
+#X msg 86 374 format 16bit;
+#X msg 102 398 format 8bit;
+#X text 189 358 format defines the resolution of the sent signal;
+#X text 347 480 the signals to send;
+#X floatatom 19 558 5 0 0 0 - - -;
+#X text 63 559 status: 1 = connected 0 = disconnected;
+#X msg 19 273 connect localhost 8008;
+#X text 15 13 netreceive~/netsend~;
+#X text 15 31 written by Olaf Matthes <olaf.matthes@gmx.de>;
+#X text 161 181 receives 4 channels on port 8808;
+#X text 186 274 connect to <hostname> <port>;
+#X text 203 421 change number of channels;
+#X text 200 376 float is the most expensive with the best resolution
+(32bit) \, default is 16bit;
+#X msg 109 422 channels 2;
+#X msg 38 298 connect 255.255.255.255 8008;
+#X text 14 50 commissioned by the Society for Arts and Technology [SAT]
+\, Montreal \, Quebec \, Canada \, http://www.sat.qc.at/;
+#X obj 269 222 print;
+#X obj 18 96 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 46 97 kick;
+#X msg 51 122 buffer 0.25;
+#X msg 62 149 print;
+#X obj 87 539 print;
+#X floatatom 224 224 5 0 0 0 - - -;
+#X text 220 298 broadcast to everybody on your local subnet listening
+on the specified port (in UDP mode only!);
+#X obj 112 448 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 137 448 get info;
+#X text 226 252 connect to <hostname> <port>;
+#X msg 23 250 connect 192.168.1.10 8008;
+#X connect 0 0 2 0;
+#X connect 0 1 3 0;
+#X connect 0 2 4 0;
+#X connect 0 3 5 0;
+#X connect 0 4 35 0;
+#X connect 0 5 29 0;
+#X connect 1 0 17 0;
+#X connect 1 1 34 0;
+#X connect 6 0 1 0;
+#X connect 7 0 1 1;
+#X connect 8 0 1 2;
+#X connect 9 0 1 3;
+#X connect 11 0 1 0;
+#X connect 12 0 1 0;
+#X connect 13 0 1 0;
+#X connect 14 0 1 0;
+#X connect 19 0 1 0;
+#X connect 26 0 1 0;
+#X connect 27 0 1 0;
+#X connect 30 0 0 0;
+#X connect 31 0 0 0;
+#X connect 32 0 0 0;
+#X connect 33 0 0 0;
+#X connect 37 0 1 0;
+#X connect 40 0 1 0;
diff --git a/l2ork_addons/raspberry_pi/netsend_tilde/float_cast.h b/l2ork_addons/raspberry_pi/netsend_tilde/float_cast.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ebc4bb448ef9d5108687c015aa9063cce6eff5c
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netsend_tilde/float_cast.h
@@ -0,0 +1,203 @@
+/*
+** Copyright (C) 2001-2003 Erik de Castro Lopo <erikd@mega-nerd.com>
+**  
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Version 1.3 */
+
+
+/*============================================================================
+**	On Intel Pentium processors (especially PIII and probably P4), converting
+**	from float to int is very slow. To meet the C specs, the code produced by
+**	most C compilers targeting Pentium needs to change the FPU rounding mode
+**	before the float to int conversion is performed.
+**
+**	Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
+**	is this flushing of the pipeline which is so slow.
+**
+**	Fortunately the ISO C99 specifications define the functions lrint, lrintf,
+**	llrint and llrintf which fix this problem as a side effect.
+**
+**	On Unix-like systems, the configure process should have detected the
+**	presence of these functions. If they weren't found we have to replace them
+**	here with a standard C cast.
+*/
+
+/*
+**	The C99 prototypes for lrint and lrintf are as follows:
+**
+**		long int lrintf (float x) ;
+**		long int lrint  (double x) ;
+*/
+
+// #include "config.h"
+
+/*
+**	The presence of the required functions are detected during the configure
+**	process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
+**	the config.h file.
+*/
+
+#define  HAVE_LRINT_REPLACEMENT 0
+
+#if (HAVE_LRINT && HAVE_LRINTF)
+
+	/*
+	**	These defines enable functionality introduced with the 1999 ISO C
+	**	standard. They must be defined before the inclusion of math.h to
+	**	engage them. If optimisation is enabled, these functions will be
+	**	inlined. With optimisation switched off, you have to link in the
+	**	maths library using -lm.
+	*/
+
+	#define	_ISOC9X_SOURCE	1
+	#define _ISOC99_SOURCE	1
+
+	#define	__USE_ISOC9X	1
+	#define	__USE_ISOC99	1
+
+	#include	<math.h>
+
+#elif (defined (WIN32) || defined (_WIN32))
+
+	#undef   HAVE_LRINT_REPLACEMENT
+	#define  HAVE_LRINT_REPLACEMENT 1
+	#include	<math.h>
+
+	/*
+	**	Win32 doesn't seem to have these functions.
+	**	Therefore implement inline versions of these functions here.
+	*/
+
+	__inline long int
+	lrint (double flt)
+	{	int intgr;
+
+		_asm
+		{	fld flt
+			fistp intgr
+			} ;
+
+		return intgr ;
+	}
+
+	__inline long int
+	lrintf (float flt)
+	{	int intgr;
+
+		_asm
+		{	fld flt
+			fistp intgr
+			} ;
+
+		return intgr ;
+	}
+
+#elif (defined (__MWERKS__) && defined (macintosh))
+
+	/* This MacOS 9 solution was provided by Stephane Letz */
+
+	#undef   HAVE_LRINT_REPLACEMENT
+	#define  HAVE_LRINT_REPLACEMENT 1
+	#include   <math.h>
+
+	#undef	lrint
+	#undef	lrintf
+
+	#define	lrint   double2int
+	#define	lrintf  float2int
+
+	inline int
+	float2int (register float in)
+	{	long res [2] ;
+
+		asm
+		{	fctiw	in,in
+		  	stfd	 in,res
+	  	}
+		return res [1] ;
+	} /* float2int */
+
+	inline int
+	double2int (register double in)
+	{	long res [2] ;
+
+		asm
+		{	fctiw	in,in
+			stfd	 in,res
+	  	}
+		return res [1] ;
+	} /* double2int */
+
+#elif (defined (__MACH__) && defined (__APPLE__))
+
+	/* For Apple MacOSX. */
+
+	#undef   HAVE_LRINT_REPLACEMENT
+	#define  HAVE_LRINT_REPLACEMENT 1
+	#include   <math.h>
+
+	#undef lrint
+	#undef lrintf
+
+	#define lrint	double2int
+	#define lrintf	float2int
+
+	inline static long int
+	float2int (register float in)
+	{	int res [2] ;
+
+		__asm__ __volatile__
+		(	"fctiw	%1, %1\n\t"
+		  	"stfd	%1, %0"
+			: "=m" (res)	/* Output */
+			: "f" (in)		/* Input */
+			: "memory"
+			) ;
+
+		return res [1] ;
+	} /* lrintf */
+
+	inline static long int
+	double2int (register double in)
+	{	int res [2] ;
+
+		__asm__ __volatile__
+		(	"fctiw	%1, %1\n\t"
+		  	"stfd	%1, %0"
+			: "=m" (res)	/* Output */
+			: "f" (in)		/* Input */
+			: "memory"
+			) ;
+
+		return res [1] ;
+	} /* lrint */
+
+#else
+	#ifndef __sgi
+	#warning "Don't have the functions lrint() and lrintf()."
+	#warning "Replacing these functions with a standard C cast."
+	#endif
+
+	#include	<math.h>
+
+	#define	lrint(dbl)		((int) (dbl))
+	#define	lrintf(flt)		((int) (flt))
+
+#endif
+
+
+
diff --git a/l2ork_addons/raspberry_pi/netsend_tilde/makefile b/l2ork_addons/raspberry_pi/netsend_tilde/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c13e789281d0459e0acb02c0c97d8d867c84b8d0
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netsend_tilde/makefile
@@ -0,0 +1,4 @@
+NAME=netsend~
+CSYM=netsend_tilde
+
+include ../makefile.include
diff --git a/l2ork_addons/raspberry_pi/netsend_tilde/netsend~.c b/l2ork_addons/raspberry_pi/netsend_tilde/netsend~.c
new file mode 100644
index 0000000000000000000000000000000000000000..7bee7c3e5947dc06dda2ac7f9d2cef01fd370ed7
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netsend_tilde/netsend~.c
@@ -0,0 +1,1056 @@
+/* ------------------------ netsend~ ------------------------------------------ */
+/*                                                                              */
+/* Tilde object to send uncompressed audio data to netreceive~.                 */
+/* Written by Olaf Matthes <olaf.matthes@gmx.de>.                               */
+/* Based on streamout~ by Guenter Geiger.                                       */
+/* Get source at http://www.akustische-kunst.org/                               */
+/*                                                                              */
+/* This program is free software; you can redistribute it and/or                */
+/* modify it under the terms of the GNU General Public License                  */
+/* as published by the Free Software Foundation; either version 2               */
+/* of the License, or (at your option) any later version.                       */
+/*                                                                              */
+/* See file LICENSE for further informations on licensing terms.                */
+/*                                                                              */
+/* This program is distributed in the hope that it will be useful,              */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of               */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
+/* GNU General Public License for more details.                                 */
+/*                                                                              */
+/* You should have received a copy of the GNU General Public License            */
+/* along with this program; if not, write to the Free Software                  */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  */
+/*                                                                              */
+/* Based on PureData by Miller Puckette and others.                             */
+/*                                                                              */
+/* This project was commissioned by the Society for Arts and Technology [SAT],  */
+/* Montreal, Quebec, Canada, http://www.sat.qc.ca/.                             */
+/*                                                                              */
+/* ---------------------------------------------------------------------------- */
+
+#ifdef PD
+#include "m_pd.h"
+#else
+#include "ext.h"
+#include "z_dsp.h"
+#endif
+
+#include "netsend~.h"
+#include "float_cast.h"	/* tools for fast conversion from float to int */
+
+#ifdef USE_FAAC
+#include "faac/faac.h"
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#if defined(__linux__) || defined(__apple__)
+#include <sys/socket.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <pthread.h>
+#define SOCKET_ERROR -1
+#endif
+#ifdef _WINDOWS
+#include <winsock.h>
+#include "pthread.h"
+#endif
+
+#ifdef _WINDOWS
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#ifdef MSG_NOSIGNAL
+#define SEND_FLAGS /*MSG_DONTWAIT|*/MSG_NOSIGNAL
+#else
+#define SEND_FLAGS 0
+#endif
+
+#ifndef SOL_IP
+#define SOL_IP IPPROTO_IP
+#endif
+
+
+/* Utility functions */
+
+static int netsend_tilde_sockerror(char *s)
+{
+#ifdef _WINDOWS
+    int err = WSAGetLastError();
+    if (err == 10054) return 1;
+    else if (err == 10053) post("netsend~: %s: software caused connection abort (%d)", s, err);
+    else if (err == 10055) post("netsend~: %s: no buffer space available (%d)", s, err);
+    else if (err == 10060) post("netsend~: %s: connection timed out (%d)", s, err);
+    else if (err == 10061) post("netsend~: %s: connection refused (%d)", s, err);
+    else post("netsend~: %s: %s (%d)", s, strerror(err), err);
+#else
+    int err = errno;
+    post("netsend~: %s: %s (%d)", s, strerror(err), err);
+#endif
+#ifdef _WINDOWS
+	if (err == WSAEWOULDBLOCK)
+#endif
+#if defined(__linux__) || defined(__apple__)
+	if (err == EAGAIN)
+#endif
+	{
+		return 1;	/* recoverable error */
+	}
+	return 0;	/* indicate non-recoverable error */
+}
+
+
+
+static void netsend_tilde_closesocket(int fd)
+{
+#if defined(__linux__) || defined(__apple__)
+	close(fd);
+#endif
+#ifdef NT
+	closesocket(fd);
+#endif
+}
+
+
+/* ------------------------ netsend~ ----------------------------- */
+
+
+#ifdef PD
+static t_class *netsend_tilde_class;
+#else
+static void *netsend_tilde_class;
+#endif
+
+static t_symbol *ps_nothing, *ps_localhost;
+static t_symbol *ps_format, *ps_channels, *ps_framesize, *ps_overflow, *ps_underflow;
+static t_symbol *ps_queuesize, *ps_average, *ps_sf_float, *ps_sf_16bit, *ps_sf_8bit;
+static t_symbol *ps_sf_mp3, *ps_sf_aac, *ps_sf_unknown, *ps_bitrate, *ps_hostname;
+
+
+typedef struct _netsend_tilde
+{
+#ifdef PD
+	t_object x_obj;
+	t_outlet *x_outlet;
+	t_outlet *x_outlet2;
+	t_clock *x_clock;
+#else
+	t_pxobject x_obj;
+	void *x_outlet;
+	void *x_outlet2;
+	void *x_clock;
+#endif
+	int x_fd;
+	int x_protocol;
+	t_tag x_tag;
+	t_symbol* x_hostname;
+	int x_portno;
+	int x_connectstate;
+	char *x_cbuf;
+	int x_cbufsize;
+	int x_blocksize;
+	int x_blockspersend;
+	int x_blockssincesend;
+
+	long x_samplerate;          /* samplerate we're running at */
+	int x_vecsize;              /* current DSP signal vector size */
+	int x_ninlets;              /* number of inlets */
+	int x_channels;             /* number of channels we want to stream */
+	int x_format;               /* format of streamed audio data */
+	int x_bitrate;              /* specifies bitrate for compressed formats */
+	int x_count;                /* total number of audio frames */
+	t_int **x_myvec;            /* vector we pass on in the DSP routine */
+
+#ifdef USE_FAAC
+    unsigned char *x_faacbuf;	/* data returned by encoder */
+	faacEncHandle x_faac;
+#endif
+
+    pthread_mutex_t   x_mutex;
+    pthread_cond_t    x_requestcondition;
+    pthread_cond_t    x_answercondition;
+    pthread_t         x_childthread;
+} t_netsend_tilde;
+
+
+
+static void netsend_tilde_notify(t_netsend_tilde *x)
+{
+	pthread_mutex_lock(&x->x_mutex);
+	x->x_childthread = 0;
+	outlet_float(x->x_outlet, x->x_connectstate);
+	pthread_mutex_unlock(&x->x_mutex);
+}
+
+
+static void netsend_tilde_disconnect(t_netsend_tilde *x)
+{
+	pthread_mutex_lock(&x->x_mutex);
+	if (x->x_fd != -1)
+	{
+		netsend_tilde_closesocket(x->x_fd);
+		x->x_fd = -1;
+		x->x_connectstate = 0;
+		outlet_float(x->x_outlet, 0);
+	}
+	pthread_mutex_unlock(&x->x_mutex);
+}
+
+
+static void *netsend_tilde_doconnect(void *zz)
+{
+	t_netsend_tilde *x = (t_netsend_tilde *)zz;
+    struct sockaddr_in server;
+    struct hostent *hp;
+	int intarg = 1;
+    int sockfd;
+    int portno;
+	t_symbol *hostname;
+	
+	pthread_mutex_lock(&x->x_mutex);
+    hostname = x->x_hostname;
+	portno = x->x_portno;
+	pthread_mutex_unlock(&x->x_mutex);
+
+    /* create a socket */
+    sockfd = socket(AF_INET, x->x_protocol, 0);
+    if (sockfd < 0)
+    {
+         post("netsend~: connection to %s on port %d failed", hostname->s_name,portno); 
+         netsend_tilde_sockerror("socket");
+		 x->x_childthread = 0;
+         return (0);
+    }
+
+    /* connect socket using hostname provided in command line */
+    server.sin_family = AF_INET;
+    hp = gethostbyname(x->x_hostname->s_name);
+    if (hp == 0)
+    {
+        post("netsend~: bad host?");
+		x->x_childthread = 0;
+        return (0);
+    }
+
+    /* for stream (TCP) sockets, specify "nodelay" */
+    if (x->x_protocol == SOCK_STREAM)
+    {
+		intarg = 1;
+		if (setsockopt(sockfd, SOL_IP, TCP_NODELAY, (const char *)&intarg, sizeof(intarg)) < 0)
+    			error("netsend~: setsockopt(TCP_NODELAY) failed");
+	}
+
+#ifdef SO_PRIORITY
+    /* set high priority, LINUX only */
+	intarg = 6;	/* select a priority between 0 and 7 */
+    if (setsockopt(sockfd, SOL_SOCKET, SO_PRIORITY, (const char*)&intarg, sizeof(int)) < 0)
+    {
+		error("netsend~: setsockopt(SO_PRIORITY) failed");
+    }
+#endif
+
+    memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+
+    /* assign client port number */
+    server.sin_port = htons((unsigned short)portno);
+
+    /* try to connect */
+    if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
+    {
+        netsend_tilde_sockerror("connecting stream socket");
+        netsend_tilde_closesocket(sockfd);
+		x->x_childthread = 0;
+        return (0);
+    }
+
+    post("netsend~: connected host %s on port %d", hostname->s_name, portno);
+
+	pthread_mutex_lock(&x->x_mutex);
+    x->x_fd = sockfd;
+	x->x_connectstate = 1;
+	clock_delay(x->x_clock, 0);
+	pthread_mutex_unlock(&x->x_mutex);
+	return (0);
+}
+
+
+
+#ifdef PD
+static void netsend_tilde_connect(t_netsend_tilde *x, t_symbol *host, t_floatarg fportno)
+#else
+static void netsend_tilde_connect(t_netsend_tilde *x, t_symbol *host, long fportno)
+#endif
+{
+	pthread_mutex_lock(&x->x_mutex);
+    if (x->x_childthread != 0)
+    {
+		 pthread_mutex_unlock(&x->x_mutex);
+         post("netsend~: already trying to connect");
+         return;
+    }
+    if (x->x_fd != -1)
+    {
+		 pthread_mutex_unlock(&x->x_mutex);
+         post("netsend~: already connected");
+         return;
+    }
+
+	if (host != ps_nothing)
+		x->x_hostname = host;
+	else
+		x->x_hostname = ps_localhost;
+
+    if (!fportno)
+		x->x_portno = DEFAULT_PORT;
+    else
+		x->x_portno = (int)fportno;
+    x->x_count = 0;
+
+	/* start child thread to connect */
+    pthread_create(&x->x_childthread, 0, netsend_tilde_doconnect, x);
+	pthread_mutex_unlock(&x->x_mutex);
+}
+
+
+
+#ifdef USE_FAAC
+static void netsend_tilde_faac_deinit(t_netsend_tilde *x)
+{
+	if (x->x_faac)
+		faacEncClose(x->x_faac);
+	x->x_faac = NULL;
+}
+
+
+static int netsend_tilde_faac_init(t_netsend_tilde *x)
+{
+	faacEncConfigurationPtr faac_format;
+	char *faac_id_string;
+	char *faac_copyright_string;
+	unsigned long samplesInput, maxBytesOutput;
+    unsigned int mpegVersion = MPEG2;
+	unsigned int channels = x->x_channels;
+
+    if (!faacEncGetVersion(&faac_id_string, &faac_copyright_string) == FAAC_CFG_VERSION)
+		return -1;
+
+    /* open the encoder library */
+    x->x_faac = faacEncOpen(x->x_samplerate, channels, &samplesInput, &maxBytesOutput);
+
+    /* put the options in the configuration struct */
+    faac_format = faacEncGetCurrentConfiguration(x->x_faac);
+    faac_format->aacObjectType = MAIN; // LOW; /* MAIN, LOW or LTP */
+    faac_format->mpegVersion = MPEG2;
+    faac_format->useTns = 1;
+    if (channels >= 6)
+	{
+        faac_format->useLfe = 1;
+		faac_format->allowMidside = 0;
+	}
+    else
+	{
+        faac_format->useLfe = 0;
+		faac_format->allowMidside = 1;
+	}
+	if (x->x_bitrate)
+		faac_format->bitRate = (x->x_bitrate * 1000) / channels;
+    faac_format->bandWidth = 0;
+    faac_format->outputFormat = 1;			/* 0 = Raw; 1 = ADTS */
+    faac_format->inputFormat = FAAC_INPUT_FLOAT;	/* input is float but scaled by 32768 */
+    if (!faacEncSetConfiguration(x->x_faac, faac_format))
+	{
+        error("netsend~: faac: unsupported format settings");
+		faacEncClose(x->x_faac);
+		x->x_faac = NULL;
+        return -1;
+    }
+	return 0;
+}
+
+
+static int netsend_tilde_faac_encode(t_netsend_tilde *x)
+{
+	static const int encbufsize = 1.25 * DEFAULT_AUDIO_BUFFER_SIZE + 7200;
+    unsigned int samples = x->x_blocksize * x->x_tag.channels;
+	float *bp = (float *)x->x_cbuf;
+
+    	/* encode AAC */
+	int ret = faacEncEncode(x->x_faac, (int32_t *)bp, samples, x->x_faacbuf, encbufsize);
+
+		/* check result */
+    if (ret < 0)
+    {
+		error("netsend~: faac: encoding failed (%d)", ret);
+        faacEncClose(x->x_faac);
+        x->x_faac = NULL;
+		return -1;
+    }
+
+	return ret;	/* return total number of AAC samples (bytes) we got */
+}
+#endif
+
+static t_int *netsend_tilde_perform(t_int *w)
+{
+    t_netsend_tilde* x = (t_netsend_tilde*) (w[1]);
+    int n = (int)(w[2]);
+	t_float *in[DEFAULT_AUDIO_CHANNELS];
+	const int offset = 3;
+    char* bp = NULL;
+    int i, length = x->x_blocksize * SF_SIZEOF(x->x_tag.format) * x->x_tag.channels;
+    int sent = 0;
+
+	pthread_mutex_lock(&x->x_mutex);
+
+	for (i = 0; i < x->x_ninlets; i++)
+		in[i] = (t_float *)(w[offset + i]);
+
+	if (n != x->x_vecsize)	/* resize buffer */
+	{
+		x->x_vecsize = n;
+		x->x_blockspersend = x->x_blocksize / x->x_vecsize;
+		x->x_blockssincesend = 0;
+		length = x->x_blocksize * SF_SIZEOF(x->x_tag.format) * x->x_tag.channels;
+	}
+
+    /* format the buffer */
+    switch (x->x_tag.format)
+	{
+		case SF_FLOAT:
+		{
+			t_float* fbuf = (t_float *)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
+			while (n--) 
+				for (i = 0; i < x->x_tag.channels; i++)
+					*fbuf++ = *(in[i]++);
+			break;
+		}
+		case SF_16BIT:
+		{
+			short* cibuf = (short *)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
+			while (n--) 
+				for (i = 0; i < x->x_tag.channels; i++)
+					*cibuf++ = (short)lrint(32767.0 * *(in[i]++));
+			break;
+		}
+		case SF_8BIT:
+		{
+			unsigned char*  cbuf = (unsigned char*)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
+			while (n--) 
+				for (i = 0; i < x->x_tag.channels; i++)
+					*cbuf++ = (unsigned char)(128. * (1.0 + *(in[i]++)));
+			break;
+		}
+#ifdef USE_FAAC
+		case SF_AAC:
+		{
+			/* same as SF_FLOAT but * 32767 and no byteswapping required */
+			t_float* fbuf = (t_float *)x->x_cbuf + (x->x_blockssincesend * x->x_vecsize * x->x_tag.channels);
+			while (n--) 
+				for (i = 0; i < x->x_tag.channels; i++)
+					*fbuf++ = 32767.0 * *(in[i]++);
+			break;
+		}
+#endif
+		default:
+			 break;
+    }
+
+	if (!(x->x_blockssincesend < x->x_blockspersend - 1))	/* time to send the buffer */
+	{
+		x->x_blockssincesend = 0;
+		x->x_count++;	/* count data packet we're going to send */
+
+		if (x->x_fd != -1)
+		{
+#ifdef USE_FAAC
+			if (x->x_tag.format == SF_AAC)
+			{
+				/* encode PCM to AAC and return new framesize */
+				length = netsend_tilde_faac_encode(x);
+				if (length <= 0)
+				{
+					if (length == 0) error("netsend~: skipping empty aac data frame");
+					else error("netsend~: error encoding AAC");
+					x->x_count--;
+					goto bail;
+				}
+				bp = (char *)x->x_faacbuf;
+			}
+			else
+#endif
+				bp = (char *)x->x_cbuf;
+
+			/* fill in the header tag */
+			x->x_tag.framesize = length;
+			x->x_tag.count = x->x_count;
+
+			 /* send the format tag */
+			if (send(x->x_fd, (char*)&x->x_tag, sizeof(t_tag), SEND_FLAGS) < 0)
+			{
+				netsend_tilde_sockerror("send tag");
+				pthread_mutex_unlock(&x->x_mutex);
+				netsend_tilde_disconnect(x);
+				return (w + offset + x->x_ninlets);
+			}
+         
+			if (x->x_protocol == SOCK_STREAM) /* TCP: send all the data at once */
+			{
+				/* send the buffer */
+				for (sent = 0; sent < length;)
+				{
+					int ret = 0;
+					ret = send(x->x_fd, bp, length - sent, SEND_FLAGS);
+					if (ret <= 0)
+					{
+						netsend_tilde_sockerror("send data");
+						pthread_mutex_unlock(&x->x_mutex);
+						netsend_tilde_disconnect(x);
+						return (w + offset + x->x_ninlets);
+					}
+					else
+					{
+						sent += ret;
+						bp += ret;
+					}
+				}
+			}
+			else	/* UDP: max. packet size is 64k (incl. headers) so we have to split */
+			{
+#ifdef __APPLE__
+				/* WARING: due to a 'bug' (maybe Apple would call it a feature?) in OS X
+				   send calls with data packets larger than 16k fail with error number 40!
+				   Thus we have to split the data packets into several packets that are 
+				   16k in size. The other side will reassemble them again. */
+
+				int size = DEFAULT_UDP_PACKT_SIZE;
+				if (length < size)	/* maybe data fits into one packet? */
+					size = length;
+
+				/* send the buffer */
+				for (sent = 0; sent < length;)
+				{
+					int ret = 0;
+					ret = send(x->x_fd, bp, size, SEND_FLAGS);
+					if (ret <= 0)
+					{
+						netsend_tilde_sockerror("send data");
+						pthread_mutex_unlock(&x->x_mutex);
+						netsend_tilde_disconnect(x);
+						return (w + offset + x->x_ninlets);
+					}
+					else
+					{
+						bp += ret;
+						sent += ret;
+						if ((length - sent) < size)
+							size = length - sent;
+					}
+				}
+#else
+				/* send the buffer, the OS might segment it into smaller packets */
+				int ret = send(x->x_fd, bp, length, SEND_FLAGS);
+				if (ret <= 0)
+				{
+					netsend_tilde_sockerror("send data");
+					pthread_mutex_unlock(&x->x_mutex);
+					netsend_tilde_disconnect(x);
+					return (w + offset + x->x_ninlets);
+				}
+#endif
+			}
+		}
+
+#ifdef USE_FAAC
+bail:
+#endif
+		/* check whether user has updated any parameters */
+		if (x->x_tag.channels != x->x_channels)
+		{
+#ifdef USE_FAAC
+			/* reinit FAAC if format is SF_AAC */
+			if (x->x_tag.format == SF_AAC)
+			{
+				netsend_tilde_faac_deinit(x);
+				netsend_tilde_faac_init(x);
+			}
+#endif
+			x->x_tag.channels = x->x_channels;
+		}
+		if (x->x_tag.format != x->x_format)
+		{
+#ifdef USE_FAAC
+			/* deinit FAAC if format was SF_AAC */
+			if ((x->x_format != SF_AAC) && (x->x_tag.format == SF_AAC))
+			{
+				netsend_tilde_faac_deinit(x);
+			}
+#endif
+			x->x_tag.format = x->x_format;
+		}
+	}
+	else
+	{
+		x->x_blockssincesend++;
+	}
+	pthread_mutex_unlock(&x->x_mutex);
+    return (w + offset + x->x_ninlets);
+}
+
+
+
+static void netsend_tilde_dsp(t_netsend_tilde *x, t_signal **sp)
+{
+	int i;
+
+	pthread_mutex_lock(&x->x_mutex);
+
+	x->x_myvec[0] = (t_int*)x;
+	x->x_myvec[1] = (t_int*)sp[0]->s_n;
+
+	x->x_samplerate = sp[0]->s_sr;
+
+	for (i = 0; i < x->x_ninlets; i++)
+	{
+		x->x_myvec[2 + i] = (t_int*)sp[i]->s_vec;
+	}
+
+	pthread_mutex_unlock(&x->x_mutex);
+
+	if (DEFAULT_AUDIO_BUFFER_SIZE % sp[0]->s_n)
+	{
+		error("netsend~: signal vector size too large (needs to be even divisor of %d)", DEFAULT_AUDIO_BUFFER_SIZE);
+	}
+	else
+	{
+#ifdef PD
+		dsp_addv(netsend_tilde_perform, x->x_ninlets + 2, (t_int*)x->x_myvec);
+#else
+		dsp_addv(netsend_tilde_perform, x->x_ninlets + 2, (void**)x->x_myvec);
+#endif
+	}
+}
+
+
+#ifdef PD
+static void netsend_tilde_channels(t_netsend_tilde *x, t_floatarg channels)
+#else
+static void netsend_tilde_channels(t_netsend_tilde *x, long channels)
+#endif
+{
+	pthread_mutex_lock(&x->x_mutex);
+	if (channels >= 0 && channels <= DEFAULT_AUDIO_CHANNELS)
+	{
+		x->x_channels = (int)channels;
+		post("netsend~: channels set to %d", (int)channels);
+	}
+	pthread_mutex_unlock(&x->x_mutex);
+}
+
+
+
+#ifdef PD
+static void netsend_tilde_format(t_netsend_tilde *x, t_symbol* form, t_floatarg bitrate)
+#else
+static void netsend_tilde_format(t_netsend_tilde *x, t_symbol* form, long bitrate)
+#endif
+{
+	pthread_mutex_lock(&x->x_mutex);
+	if (!strncmp(form->s_name,"float", 5) && x->x_tag.format != SF_FLOAT)
+	{
+		x->x_format = (int)SF_FLOAT;
+	}
+	else if (!strncmp(form->s_name,"16bit", 5) && x->x_tag.format != SF_16BIT)
+	{
+		x->x_format = (int)SF_16BIT;
+	}
+	else if (!strncmp(form->s_name,"8bit", 4) && x->x_tag.format != SF_8BIT)
+	{
+		x->x_format = (int)SF_8BIT;
+	}
+	else if (!strncmp(form->s_name,"mp3", 3) && x->x_tag.format != SF_MP3)
+	{
+		error("netsend~: not compiled with mp3 support");
+		pthread_mutex_unlock(&x->x_mutex);
+		return;
+	}
+	else if (!strncmp(form->s_name,"aac", 3) && x->x_tag.format != SF_AAC)
+	{
+#ifdef USE_FAAC
+		x->x_bitrate = (int)bitrate;
+		if (netsend_tilde_faac_init(x) < 0)
+		{
+			pthread_mutex_unlock(&x->x_mutex);
+			return;
+		}
+		x->x_format = (int)SF_AAC;
+#else
+		error("netsend~: not compiled with aac support");
+		pthread_mutex_unlock(&x->x_mutex);
+		return;
+#endif
+	}
+
+	post("netsend~: format set to %s", form->s_name);
+	pthread_mutex_unlock(&x->x_mutex);
+}
+
+
+/* set hostname to send to */
+static void netsend_tilde_host(t_netsend_tilde *x, t_symbol* host)
+{
+	pthread_mutex_lock(&x->x_mutex);
+	if (host != ps_nothing)
+		x->x_hostname = host;
+	else
+		x->x_hostname = ps_localhost;
+
+	if (x->x_fd != -1)
+	{
+		pthread_mutex_unlock(&x->x_mutex);
+		netsend_tilde_connect(x,x->x_hostname, (float)x->x_portno);
+		return;
+	}
+	pthread_mutex_unlock(&x->x_mutex);
+}
+
+
+
+#ifdef PD
+static void netsend_tilde_float(t_netsend_tilde* x, t_floatarg arg)
+#else
+static void netsend_tilde_float(t_netsend_tilde* x, double arg)
+#endif
+{
+	if (arg == 0.0)
+		netsend_tilde_disconnect(x);
+	else
+		netsend_tilde_connect(x,x->x_hostname,(float) x->x_portno);
+}
+
+
+/* send stream info when banged */
+static void netsend_tilde_bang(t_netsend_tilde *x)
+{
+	t_atom list[2];
+	t_symbol *sf_format;
+	t_float bitrate;
+
+	bitrate = (t_float)((SF_SIZEOF(x->x_tag.format) * x->x_samplerate * 8 * x->x_tag.channels) / 1000.);
+
+	switch (x->x_tag.format)
+	{
+		case SF_FLOAT:
+		{
+			sf_format = ps_sf_float;
+			break;
+		}
+		case SF_16BIT:
+		{
+			sf_format = ps_sf_16bit;
+			break;
+		}
+		case SF_8BIT:
+		{
+			sf_format = ps_sf_8bit;
+			break;
+		}
+		case SF_MP3:
+		{
+			sf_format = ps_sf_mp3;
+			break;
+		}
+		case SF_AAC:
+		{
+			sf_format = ps_sf_aac;
+			break;
+		}
+		default:
+		{
+			sf_format = ps_sf_unknown;
+			break;
+		}
+	}
+
+#ifdef PD
+	/* --- stream information (t_tag) --- */
+	/* audio format */
+	SETSYMBOL(list, (t_symbol *)sf_format);
+	outlet_anything(x->x_outlet2, ps_format, 1, list);
+
+	/* channels */
+	SETFLOAT(list, (t_float)x->x_tag.channels);
+	outlet_anything(x->x_outlet2, ps_channels, 1, list);
+
+	/* framesize */
+	SETFLOAT(list, (t_float)x->x_tag.framesize);
+	outlet_anything(x->x_outlet2, ps_framesize, 1, list);
+
+	/* bitrate */
+	SETFLOAT(list, (t_float)bitrate);
+	outlet_anything(x->x_outlet2, ps_bitrate, 1, list);
+
+	/* IP address */
+	SETSYMBOL(list, (t_symbol *)x->x_hostname);
+	outlet_anything(x->x_outlet2, ps_hostname, 1, list);
+#else
+	/* --- stream information (t_tag) --- */
+	/* audio format */
+	SETSYM(list, ps_format);
+	SETSYM(list + 1, (t_symbol *)sf_format);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* channels */
+	SETSYM(list, ps_channels);
+	SETLONG(list + 1, (int)x->x_tag.channels);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* framesize */
+	SETSYM(list, ps_framesize);
+	SETLONG(list + 1, (int)x->x_tag.framesize);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* bitrate */
+	SETSYM(list, ps_bitrate);
+	SETFLOAT(list + 1, (t_float)bitrate);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+
+	/* IP address */
+	SETSYM(list, (t_symbol *)ps_hostname);
+	SETSYM(list + 1, x->x_hostname);
+	outlet_list(x->x_outlet2, NULL, 2, list);
+#endif
+}
+
+
+#ifdef PD
+static void *netsend_tilde_new(t_floatarg inlets, t_floatarg prot)
+#else
+static void *netsend_tilde_new(long inlets, long prot)
+#endif
+{
+	int i;
+
+#ifdef PD
+	t_netsend_tilde *x = (t_netsend_tilde *)pd_new(netsend_tilde_class);
+    if (x)
+    { 
+        for (i = sizeof(t_object); i < (int)sizeof(t_netsend_tilde); i++)  
+                ((char *)x)[i] = 0; 
+	}
+
+	x->x_ninlets = CLIP((int)inlets, 1, DEFAULT_AUDIO_CHANNELS);
+	for (i = 1; i < x->x_ninlets; i++)
+		inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+
+	x->x_outlet = outlet_new(&x->x_obj, &s_float);
+	x->x_outlet2 = outlet_new(&x->x_obj, &s_list);
+	x->x_clock = clock_new(x, (t_method)netsend_tilde_notify);
+#else
+	t_netsend_tilde *x = (t_netsend_tilde *)newobject(netsend_tilde_class);
+    if (x)
+    { 
+        for (i = sizeof(t_pxobject); i < sizeof(t_netsend_tilde); i++)  
+                ((char *)x)[i] = 0; 
+	}
+
+	x->x_ninlets = CLIP((int)inlets, 1, DEFAULT_AUDIO_CHANNELS);
+	dsp_setup((t_pxobject *)x, x->x_ninlets);
+	x->x_outlet2 = outlet_new(x, "list");
+	x->x_outlet = outlet_new(x, "int");
+	x->x_clock = clock_new(x, (method)netsend_tilde_notify);
+#endif
+
+	x->x_myvec = (t_int **)t_getbytes(sizeof(t_int *) * (x->x_ninlets + 3));
+	if (!x->x_myvec)
+	{
+		error("netsend~: out of memory");
+		return NULL;
+	}
+
+#ifdef USE_FAAC
+	/* allocate a buffer for encoded data */
+	x->x_faacbuf = (unsigned char *)t_getbytes(sizeof(char *) * (1.25 * DEFAULT_AUDIO_BUFFER_SIZE + 7200));
+	if (!x->x_faacbuf)
+	{
+		error("netsend~: out of memory");
+		return NULL;
+	}
+	x->x_faac = NULL;	/* encoder not yet nitialized */
+#endif
+
+    pthread_mutex_init(&x->x_mutex, 0);
+    pthread_cond_init(&x->x_requestcondition, 0);
+    pthread_cond_init(&x->x_answercondition, 0);
+
+	x->x_hostname = ps_localhost;
+	x->x_portno = 3000;
+	x->x_connectstate = 0;
+	x->x_childthread = 0;
+	x->x_fd = -1;
+	x->x_protocol = SOCK_STREAM;
+
+	if (prot)	/* user wants UDP */
+	{
+		x->x_protocol = SOCK_DGRAM;
+	}
+
+	x->x_tag.format = x->x_format = SF_FLOAT;
+	x->x_tag.channels = x->x_channels = x->x_ninlets;
+	x->x_tag.version = SF_BYTE_NATIVE;	/* native endianness */
+	x->x_vecsize = 64;      /* we'll update this later */
+	x->x_bitrate = 0;		/* not specified, use default */
+	x->x_cbuf = NULL;
+	x->x_blocksize = DEFAULT_AUDIO_BUFFER_SIZE;
+	x->x_blockspersend = x->x_blocksize / x->x_vecsize;
+	x->x_blockssincesend = 0;
+	x->x_cbufsize = x->x_blocksize * sizeof(t_float) * x->x_ninlets;
+	x->x_cbuf = (char *)t_getbytes(x->x_cbufsize);
+
+#if defined(__linux__) || defined(__apple__)
+	/* we don't want to get signaled in case send() fails */
+	signal(SIGPIPE, SIG_IGN);
+#endif
+
+	return (x);
+}
+
+
+
+static void netsend_tilde_free(t_netsend_tilde* x)
+{
+	netsend_tilde_disconnect(x);
+
+#ifndef PD
+	dsp_free((t_pxobject *)x);	/* free the object */
+#endif
+
+	/* free the memory */
+	if (x->x_cbuf)t_freebytes(x->x_cbuf, x->x_cbufsize);
+	if (x->x_myvec)t_freebytes(x->x_myvec, sizeof(t_int) * (x->x_ninlets + 3));
+
+#ifdef USE_FAAC
+	if (x->x_faacbuf)t_freebytes(x->x_faacbuf, sizeof(char *) * (1.25 * DEFAULT_AUDIO_BUFFER_SIZE + 7200));
+	netsend_tilde_faac_deinit(x);
+#endif
+
+	clock_free(x->x_clock);
+
+    pthread_cond_destroy(&x->x_requestcondition);
+    pthread_cond_destroy(&x->x_answercondition);
+    pthread_mutex_destroy(&x->x_mutex);
+}
+
+
+#ifdef PD
+
+void netsend_tilde_setup(void)
+{
+    netsend_tilde_class = class_new(gensym("netsend~"), (t_newmethod)netsend_tilde_new, (t_method)netsend_tilde_free,
+        sizeof(t_netsend_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+    class_addmethod(netsend_tilde_class, nullfn, gensym("signal"), 0);
+    class_addmethod(netsend_tilde_class, (t_method)netsend_tilde_dsp, gensym("dsp"), 0);
+    class_addfloat(netsend_tilde_class, netsend_tilde_float);
+    class_addbang(netsend_tilde_class, netsend_tilde_bang);
+    class_addmethod(netsend_tilde_class, (t_method)netsend_tilde_connect, gensym("connect"), A_DEFSYM, A_DEFFLOAT, 0);
+    class_addmethod(netsend_tilde_class, (t_method)netsend_tilde_disconnect, gensym("disconnect"), 0);
+    class_addmethod(netsend_tilde_class, (t_method)netsend_tilde_channels, gensym("channels"), A_FLOAT, 0);
+    class_addmethod(netsend_tilde_class, (t_method)netsend_tilde_format, gensym("format"), A_SYMBOL, A_DEFFLOAT, 0);
+    class_addmethod(netsend_tilde_class, (t_method)netsend_tilde_host, gensym("host"), A_DEFSYM, 0);
+	class_sethelpsymbol(netsend_tilde_class, gensym("netsend~"));
+	post("netsend~ v%s, (c) 2004-2005 Olaf Matthes", VERSION);
+
+	ps_nothing = gensym("");
+	ps_localhost = gensym("localhost");
+	ps_hostname = gensym("ipaddr");
+	ps_format = gensym("format");
+	ps_channels = gensym("channels");
+	ps_framesize = gensym("framesize");
+	ps_bitrate = gensym("bitrate");
+	ps_sf_float = gensym("_float_");
+	ps_sf_16bit = gensym("_16bit_");
+	ps_sf_8bit = gensym("_8bit_");
+	ps_sf_mp3 = gensym("_mp3_");
+	ps_sf_aac = gensym("_aac_");
+	ps_sf_unknown = gensym("_unknown_");
+}
+
+#else
+
+void netsend_tilde_assist(t_netsend_tilde *x, void *b, long m, long a, char *s)
+{
+	switch(m)
+	{
+		case 1: // inlet
+			switch(a)
+			{
+				case 0:
+					sprintf(s, "Control Messages & Audio Channel 1");
+					break;
+				default:
+					sprintf(s, "Audio Channel %d", (int)a + 1);
+					break;
+			}
+		break;
+		case 2: // outlet
+			switch(a)
+			{
+				case 0:
+					sprintf(s, "(Int) State of Connection");
+					break;
+			}
+		break;
+	}
+
+}
+
+void main()
+{
+#ifdef _WINDOWS
+    short version = MAKEWORD(2, 0);
+    WSADATA nobby;
+#endif /* _WINDOWS */
+
+	setup((t_messlist **)&netsend_tilde_class, (method)netsend_tilde_new, (method)netsend_tilde_free, 
+	      (short)sizeof(t_netsend_tilde), 0L, A_DEFLONG, A_DEFLONG, 0);
+
+	addmess((method)netsend_tilde_dsp, "dsp", A_CANT, 0);
+	addmess((method)netsend_tilde_connect, "connect", A_DEFSYM, A_DEFLONG, 0);
+	addmess((method)netsend_tilde_disconnect, "disconnect", 0);
+	addmess((method)netsend_tilde_format, "format", A_SYM, A_DEFLONG, 0);
+	addmess((method)netsend_tilde_channels, "channels", A_LONG, 0);
+	addmess((method)netsend_tilde_host, "host", A_DEFSYM, 0);
+	addmess((method)netsend_tilde_assist, "assist", A_CANT, 0);
+	addbang((method)netsend_tilde_bang);
+	dsp_initclass();
+	finder_addclass("System", "netsend~");
+	post("netsend~ v%s, © 2004-2005 Olaf Matthes", VERSION);
+	ps_nothing = gensym("");
+	ps_localhost = gensym("localhost");
+	ps_hostname = gensym("ipaddr");
+	ps_format = gensym("format");
+	ps_channels = gensym("channels");
+	ps_framesize = gensym("framesize");
+	ps_bitrate = gensym("bitrate");
+	ps_sf_float = gensym("_float_");
+	ps_sf_16bit = gensym("_16bit_");
+	ps_sf_8bit = gensym("_8bit_");
+	ps_sf_mp3 = gensym("_mp3_");
+	ps_sf_aac = gensym("_aac_");
+	ps_sf_unknown = gensym("_unknown_");
+
+#ifdef _WINDOWS
+    if (WSAStartup(version, &nobby)) error("netsend~: WSAstartup failed");
+#endif /* _WINDOWS */
+}
+
+#endif	/* PD */
diff --git a/l2ork_addons/raspberry_pi/netsend_tilde/netsend~.h b/l2ork_addons/raspberry_pi/netsend_tilde/netsend~.h
new file mode 100644
index 0000000000000000000000000000000000000000..874b63f25b48ea82ee4e7e6d38d9ff67db4e4425
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netsend_tilde/netsend~.h
@@ -0,0 +1,154 @@
+/* ------------------------ netsend~ ------------------------------------------ */
+/*                                                                              */
+/* Tilde object to send uncompressed audio data to netreceive~.                 */
+/* Written by Olaf Matthes <olaf.matthes@gmx.de>.                               */
+/* Based on streamout~ by Guenter Geiger.                                       */
+/* Get source at http://www.akustische-kunst.org/                               */
+/*                                                                              */
+/* This program is free software; you can redistribute it and/or                */
+/* modify it under the terms of the GNU General Public License                  */
+/* as published by the Free Software Foundation; either version 2               */
+/* of the License, or (at your option) any later version.                       */
+/*                                                                              */
+/* See file LICENSE for further informations on licensing terms.                */
+/*                                                                              */
+/* This program is distributed in the hope that it will be useful,              */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of               */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
+/* GNU General Public License for more details.                                 */
+/*                                                                              */
+/* You should have received a copy of the GNU General Public License            */
+/* along with this program; if not, write to the Free Software                  */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  */
+/*                                                                              */
+/* Based on PureData by Miller Puckette and others.                             */
+/*                                                                              */
+/* This project was commissioned by the Society for Arts and Technology [SAT],  */
+/* Montreal, Quebec, Canada, http://www.sat.qc.ca/.                             */
+/*                                                                              */
+/* ---------------------------------------------------------------------------- */
+
+
+/* This file is based on and inspired by stream.h (C) Guenter Geiger 1999.   */
+/* Some enhancements have been made with the goal of keeping compatibility   */
+/* between the stream formats of streamout~/in~ and netsend~/receive~.       */
+
+#define VERSION "1.0alpha11"
+
+#define DEFAULT_AUDIO_CHANNELS 32	    /* nax. number of audio channels we support */
+#define DEFAULT_AUDIO_BUFFER_SIZE 1024	/* number of samples in one audio block */
+#define DEFAULT_UDP_PACKT_SIZE 8192		/* number of bytes we send in one UDP datagram (OS X only) */
+#define DEFAULT_PORT 8000               /* default network port number */
+
+#ifdef _WINDOWS
+#ifndef HAVE_INT32_T
+typedef int int32_t;
+#define HAVE_INT32_T
+#endif
+#ifndef HAVE_INT16_T
+typedef short int16_t;
+#define HAVE_INT16_T
+#endif
+#ifndef HAVE_U_INT32_T
+typedef unsigned int u_int32_t;
+#define HAVE_U_INT32_T
+#endif
+#ifndef HAVE_U_INT16_T
+typedef unsigned short u_int16_t;
+#define HAVE_U_INT16_T
+#endif
+#endif
+
+#ifndef CLIP
+#define CLIP(a, lo, hi) ( (a)>(lo)?( (a)<(hi)?(a):(hi) ):(lo) )
+#endif
+
+
+/* swap 32bit t_float. Is there a better way to do that???? */
+#ifdef _WINDOWS
+__inline static float netsend_float(float f)
+#else
+inline static float netsend_float(float f)
+#endif
+{
+    union
+    {
+        float f;
+        unsigned char b[4];
+    } dat1, dat2;
+    
+    dat1.f = f;
+    dat2.b[0] = dat1.b[3];
+    dat2.b[1] = dat1.b[2];
+    dat2.b[2] = dat1.b[1];
+    dat2.b[3] = dat1.b[0];
+    return dat2.f;
+}
+
+/* swap 32bit long int */
+#ifdef _WINDOWS
+__inline static long netsend_long(long n)
+#else
+inline static long netsend_long(long n)
+#endif
+{
+    return (((n & 0xff) << 24) | ((n & 0xff00) << 8) |
+    	((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24));
+}
+
+/* swap 16bit short int */
+#ifdef _WINDOWS
+__inline static long netsend_short(long n)
+#else
+inline static short netsend_short(short n)
+#endif
+{
+    return (((n & 0xff) << 8) | ((n & 0xff00) >> 8));
+}
+
+
+/* format specific stuff */
+
+#define SF_FLOAT  1
+#define SF_DOUBLE 2		/* not implemented */
+#define SF_8BIT   10
+#define SF_16BIT  11
+#define SF_32BIT  12	/* not implemented */
+#define SF_ALAW   20	/* not implemented */
+#define SF_MP3    30    /* not implemented */
+#define SF_AAC    31    /* AAC encoding using FAAC */
+#define SF_VORBIS 40	/* not implemented */
+#define SF_FLAC   50	/* not implemented */
+
+#define SF_SIZEOF(a) (a == SF_FLOAT ? sizeof(t_float) : \
+                     a == SF_16BIT ? sizeof(short) : 1)
+
+
+/* version / byte-endian specific stuff */
+
+#define SF_BYTE_LE 1		/* little endian */
+#define SF_BYTE_BE 2		/* big endian */
+
+#if defined(_WINDOWS) || defined(__linux__) || defined(IRIX)
+#define SF_BYTE_NATIVE SF_BYTE_LE
+#else /* must be  __APPLE__ */
+#define SF_BYTE_NATIVE SF_BYTE_BE
+#endif
+
+
+typedef struct _tag {      /* size (bytes) */
+     char version;         /*    1         */
+     char format;          /*    1         */
+     long count;           /*    4         */
+     char channels;        /*    1         */
+     long framesize;       /*    4         */
+     char  extension[5];   /*    5         */
+} t_tag;                   /*--------------*/
+                           /*   16         */
+
+
+typedef struct _frame {
+     t_tag  tag;
+     char  *data;
+} t_frame;
+
diff --git a/l2ork_addons/raspberry_pi/netsend_tilde/test-netsend~.pd b/l2ork_addons/raspberry_pi/netsend_tilde/test-netsend~.pd
new file mode 100644
index 0000000000000000000000000000000000000000..d3d9cbf5f99a069fe7bc787d5560a95ef58c8131
--- /dev/null
+++ b/l2ork_addons/raspberry_pi/netsend_tilde/test-netsend~.pd
@@ -0,0 +1,72 @@
+#N canvas 291 209 642 596 10;
+#X obj 18 178 netreceive~ 8008 4;
+#X obj 19 514 netsend~ 4;
+#X obj 18 221 dac~ 1;
+#X obj 68 221 dac~ 2;
+#X obj 121 221 dac~ 3;
+#X obj 175 222 dac~ 4;
+#X obj 74 480 osc~ 440;
+#X obj 145 481 osc~ 880;
+#X obj 214 480 osc~ 990;
+#X obj 281 481 osc~ 220;
+#X text 245 515 sends 4 dsp-channels to localhost:8008;
+#X msg 62 325 disconnect;
+#X msg 76 350 format float;
+#X msg 86 374 format 16bit;
+#X msg 102 398 format 8bit;
+#X text 189 358 format defines the resolution of the sent signal;
+#X text 347 480 the signals to send;
+#X floatatom 19 558 5 0 0 0 - - -;
+#X text 63 559 status: 1 = connected 0 = disconnected;
+#X msg 19 273 connect localhost 8008;
+#X text 15 13 netreceive~/netsend~;
+#X text 15 31 written by Olaf Matthes <olaf.matthes@gmx.de>;
+#X text 161 181 receives 4 channels on port 8808;
+#X text 186 274 connect to <hostname> <port>;
+#X text 203 421 change number of channels;
+#X text 200 376 float is the most expensive with the best resolution
+(32bit) \, default is 16bit;
+#X msg 109 422 channels 2;
+#X msg 38 298 connect 255.255.255.255 8008;
+#X text 14 50 commissioned by the Society for Arts and Technology [SAT]
+\, Montreal \, Quebec \, Canada \, http://www.sat.qc.at/;
+#X obj 269 222 print;
+#X obj 18 96 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 46 97 kick;
+#X msg 51 122 buffer 0.25;
+#X msg 62 149 print;
+#X obj 87 539 print;
+#X floatatom 224 224 5 0 0 0 - - -;
+#X text 220 298 broadcast to everybody on your local subnet listening
+on the specified port (in UDP mode only!);
+#X obj 112 448 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 137 448 get info;
+#X text 226 252 connect to <hostname> <port>;
+#X msg 23 250 connect 192.168.1.10 8008;
+#X connect 0 0 2 0;
+#X connect 0 1 3 0;
+#X connect 0 2 4 0;
+#X connect 0 3 5 0;
+#X connect 0 4 35 0;
+#X connect 0 5 29 0;
+#X connect 1 0 17 0;
+#X connect 1 1 34 0;
+#X connect 6 0 1 0;
+#X connect 7 0 1 1;
+#X connect 8 0 1 2;
+#X connect 9 0 1 3;
+#X connect 11 0 1 0;
+#X connect 12 0 1 0;
+#X connect 13 0 1 0;
+#X connect 14 0 1 0;
+#X connect 19 0 1 0;
+#X connect 26 0 1 0;
+#X connect 27 0 1 0;
+#X connect 30 0 0 0;
+#X connect 31 0 0 0;
+#X connect 32 0 0 0;
+#X connect 33 0 0 0;
+#X connect 37 0 1 0;
+#X connect 40 0 1 0;