From 506b8e7dedb80d79bf015e47d92e8b8dd8284584 Mon Sep 17 00:00:00 2001
From: Hans-Christoph Steiner <eighthave@users.sourceforge.net>
Date: Sat, 16 Aug 2003 17:08:55 +0000
Subject: added files straight from Yves' sources

svn path=/trunk/externals/unauthorized/; revision=864
---
 mp3live~/INSTALL               |  21 ++
 mp3live~/Makefile              |  88 +++++
 mp3live~/README                |  65 ++++
 mp3live~/help-mp3live~.pd      | 118 +++++++
 mp3live~/interface.h           |  32 ++
 mp3live~/mp3fileout~.c         | 553 +++++++++++++++++++++++++++++++
 mp3live~/mp3streamin~.c        | 665 +++++++++++++++++++++++++++++++++++++
 mp3live~/mp3streamout~.c       | 733 +++++++++++++++++++++++++++++++++++++++++
 mp3live~/mpg123.h              | 136 ++++++++
 mp3live~/mpglib.h              |  65 ++++
 mp3live~/test-streaming-mp3.pd |  96 ++++++
 11 files changed, 2572 insertions(+)
 create mode 100644 mp3live~/INSTALL
 create mode 100644 mp3live~/Makefile
 create mode 100644 mp3live~/README
 create mode 100644 mp3live~/help-mp3live~.pd
 create mode 100644 mp3live~/interface.h
 create mode 100644 mp3live~/mp3fileout~.c
 create mode 100644 mp3live~/mp3streamin~.c
 create mode 100644 mp3live~/mp3streamout~.c
 create mode 100644 mp3live~/mpg123.h
 create mode 100644 mp3live~/mpglib.h
 create mode 100644 mp3live~/test-streaming-mp3.pd

(limited to 'mp3live~')

diff --git a/mp3live~/INSTALL b/mp3live~/INSTALL
new file mode 100644
index 0000000..63db4c7
--- /dev/null
+++ b/mp3live~/INSTALL
@@ -0,0 +1,21 @@
+You need to get lame > v3.90 installed first.
+libmp3lame.so is searched in /usr/local/lib
+( no time to write configure scripts ).
+if it's installed elsewhere, change the Makefile,
+you won't die from that.
+
+untar in /my/pd/dir/externs
+
+cd /my/pd/dir/externs/mp3live~
+
+make clean 
+
+make
+
+make install
+
+open help-mp3live~.pd
+
+Thanx for getting here.
+
+Yves/
diff --git a/mp3live~/Makefile b/mp3live~/Makefile
new file mode 100644
index 0000000..a9d6228
--- /dev/null
+++ b/mp3live~/Makefile
@@ -0,0 +1,88 @@
+NAME=mp3streamout~
+CSYM=mp3streamout_tilde
+NAMEB=mp3streamin~
+CSYMB=mp3streamin_tilde
+NAMEC=mp3fileout~
+CSYMC=mp3fileout_tilde
+
+current: pd_linux
+
+# ----------------------- NT -----------------------
+
+pd_nt: $(NAME).dll $(NAMEB).dll $(NAMEC).dll
+
+.SUFFIXES: .dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+VC="C:\Program Files\Microsoft Visual Studio\Vc98"
+
+PDNTINCLUDE = /I. /I\tcl\include /I\ftp\pd\src /I$(VC)\include
+
+PDNTLDIR = $(VC)\lib
+PDNTLIB = $(PDNTLDIR)\libc.lib \
+	$(PDNTLDIR)\oldnames.lib \
+	$(PDNTLDIR)\kernel32.lib \
+	\ftp\pd\bin\pd.lib 
+
+.c.dll:
+	cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+	link /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
+
+# ----------------------- IRIX 5.x -----------------------
+
+pd_irix5: $(NAME).pd_irix5 $(NAMEB).pd_irix5 $(NAMEC).pd_irix5
+
+.SUFFIXES: .pd_irix5
+
+SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
+
+SGIINCLUDE =  -I../../src
+
+.c.pd_irix5:
+	cc $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
+	ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
+	rm $*.o
+
+# ----------------------- IRIX 6.x -----------------------
+
+pd_irix6: $(NAME).pd_irix6 $(NAMEB).pd_irix6 $(NAMEC).pd_irix6
+
+.SUFFIXES: .pd_irix6
+
+SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+	-OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+	-Ofast=ip32
+
+.c.pd_irix6:
+	cc $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
+	ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
+	rm $*.o
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: $(NAME).pd_linux $(NAMEB).pd_linux $(NAMEC).pd_linux
+
+.SUFFIXES: .pd_linux
+
+LINUXCFLAGS = -g -DPD -DUNIX -O2 -funroll-loops -fomit-frame-pointer \
+    -Wall -W -Wshadow -Wstrict-prototypes -Werror \
+    -Wno-unused -Wno-parentheses -Wno-switch
+
+LINUXINCLUDE =  -I../../src
+
+.c.pd_linux: 
+	cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+	ld -export_dynamic  -shared -o $*.pd_linux $*.o -lc -lm -L/usr/local/lib -lmp3lame
+	#strip --strip-unneeded $*.pd_linux
+	rm -f $*.o ../$*.pd_linux
+	ln -s mp3live~/$*.pd_linux ..
+
+
+
+# ----------------------------------------------------------
+
+install:
+	cp help-*.pd ../../doc/5.reference
+
+clean:
+	rm -f *.o *.pd_* so_locations
diff --git a/mp3live~/README b/mp3live~/README
new file mode 100644
index 0000000..3af0dbb
--- /dev/null
+++ b/mp3live~/README
@@ -0,0 +1,65 @@
+Version 0.01 
+copyleft (c) 2001 by Yves Degoyon
+
+mp3live~ is a peer-to-peer mp3 streamer package
+consisting of three objects : mp3streamout~, mp3fileout~ and mp3streamin~.
+
+To install mp3live~, follow the steps from INSTALL
+
+This software is published under GPL terms.
+
+This is software with ABSOLUTELY NO WARRANTY.
+Use it at your OWN RISK. It's possible to damage e.g. hardware or your hearing
+due to a bug or for other reasons. 
+We do not warrant that the program is free of infringement of any third-party
+patents.
+
+*****************************************************************************
+
+mp3live~ has been compiled for Linux using LAME 3.92.
+The newest version of LAME can be found at sourceforge.net
+
+COPYING: you may use this source under GPL terms!
+
+PLEASE NOTE: This software may contain patented alogrithm (at least
+  patented in some countries). It may be not allowed to sell/use products
+  based on this source code in these countries. Check this out first!
+
+COPYRIGHT of MP3 music:
+  Please note, that the duplicating of copyrighted music without explicit
+  permission violates the rights of the owner.
+  And remember, copyrighted music sucks [ as well as corporate ]             
+
+*****************************************************************************
+
+	using mp3live~ external for Pure Data
+
+Open the help-mp3live~.pd to understand how it works.
+
+A note about MPEG encoding :
+
+ALLOWED QUALITY FACTOR :
+
+    -q <arg>        <arg> = 0...9.  Default  -q 5 
+                    -q 0:  Highest quality, very slow 
+                    -q 9:  Poor quality, but fast 
+    -h              Same as -q 2.   Recommended.
+    -f              Same as -q 7.   Fast, ok quality
+
+ALLOWED BITRATES :
+
+bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320
+
+BUGS :
+
+1.
+You cannot create more than MAX_DECODERS mp3streamin~ objects. The actual value is 100.
+
+2.
+Current version of lame ( 3.92 ) produces a lot of errors for quality < 5. Blame it on lame !!!!
+
+3.
+Mono is not supported. Some additional code should be added for mp3streamin~. Blame it on me !!!
+
+4.
+Resampling is not supported. Blame it on me !!!
diff --git a/mp3live~/help-mp3live~.pd b/mp3live~/help-mp3live~.pd
new file mode 100644
index 0000000..ac68464
--- /dev/null
+++ b/mp3live~/help-mp3live~.pd
@@ -0,0 +1,118 @@
+#N canvas 11 -3 941 684 10;
+#X msg 35 594 \; pd dsp 1;
+#X text 432 123 <-- settings for mp3 stream;
+#X text 492 177 1 = joint stereo (default);
+#X text 456 165 mode: 0 = stereo;
+#X text 492 189 2 = dual channel;
+#X msg 101 594 \; pd dsp 0;
+#X obj 551 317 dac~;
+#X msg 368 80 disconnect;
+#X floatatom 221 227 5 0 0;
+#X obj 221 199 mp3streamout~;
+#X msg 367 54 connect localhost 5000;
+#X msg 767 69 bang;
+#X obj 767 89 openpanel;
+#X obj 766 186 soundfiler;
+#X floatatom 767 210 10 0 0;
+#X obj 767 111 t s b;
+#X obj 767 148 pack s s;
+#X msg 766 169 read -resize \$1 \$2;
+#X obj 803 111 float \$0;
+#X text 755 50 Step 1 : Load a sound file;
+#X obj 767 128 route float;
+#X obj 123 149 tabplay~ \$0-sample;
+#X msg 123 120 bang;
+#X obj 114 627 table \$0-sample;
+#X obj 821 148 makefilename %d-sample;
+#X text 371 34 Step 2 : connect the streamer;
+#X text 8 100 Step 3 : emit a sound through the streamer;
+#X obj 234 276 env~;
+#X obj 67 310 timer;
+#X obj 207 276 > 0;
+#X obj 159 276 route 1;
+#X obj 122 276 t b f;
+#X floatatom 121 340 5 0 0;
+#X obj 80 276 spigot;
+#X msg 102 256 0;
+#X msg 130 256 1;
+#X text 453 135 (bitrate \, mode \, quality);
+#X text 453 227 Note : resampling is not supported for now;
+#X text 454 238 Note : see the README for allowed bitrate;
+#X text 30 9 mp3live~ : mp3streamout~ / mp3streamin~;
+#X text 30 20 peer-to-peer mp3 streaming \, written by ydegoyon@free.fr
+;
+#X msg 342 147 mpeg 32 2 9;
+#X text 492 202 3 = mono ( not supported );
+#X text 455 153 bitrate: bitrate of stream \, def. 128kbit/s;
+#X text 452 215 quality: 5 = high \, 9 = low;
+#X text 85 360 streamer latency (ms);
+#X obj 35 573 loadbang;
+#X msg 343 123 mpeg 128 0 5;
+#X obj 536 270 mp3streamin~ 5000 1;
+#X symbolatom 639 300 10 0 0;
+#X text 622 316 Incomer's address;
+#X floatatom 229 496 5 0 0;
+#X floatatom 327 498 5 0 0;
+#X text 282 366 Step 3 bis : emit a file through the streamer;
+#X msg 298 386 bang;
+#X msg 299 423 open \$1;
+#X msg 393 410 disconnect;
+#X msg 393 391 connect localhost 5000;
+#X msg 393 429 start;
+#X msg 438 430 stop;
+#X obj 298 406 openpanel;
+#X text 292 522 Number of frames emitted;
+#X text 160 515 Connection state;
+#X text 31 36 Warning : mp3fileout~ will not read ANY mp3 file \,;
+#X text 30 46 but \, at least \, those produced with mp3write~.;
+#X msg 474 430 resume;
+#X msg 524 429 seek 10000;
+#X text 391 503 A bang is emitted at the end of the file;
+#X obj 301 454 mp3fileout~;
+#X obj 389 485 print thisistheend;
+#X connect 7 0 9 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 11 0 12 0;
+#X connect 12 0 15 0;
+#X connect 13 0 14 0;
+#X connect 15 0 16 0;
+#X connect 15 1 18 0;
+#X connect 16 0 17 0;
+#X connect 17 0 13 0;
+#X connect 18 0 20 0;
+#X connect 20 0 24 0;
+#X connect 21 0 9 0;
+#X connect 21 0 9 1;
+#X connect 22 0 21 0;
+#X connect 22 0 28 0;
+#X connect 22 0 35 0;
+#X connect 24 0 16 1;
+#X connect 27 0 29 0;
+#X connect 28 0 32 0;
+#X connect 29 0 30 0;
+#X connect 30 0 31 0;
+#X connect 31 0 33 0;
+#X connect 32 0 34 0;
+#X connect 33 0 28 1;
+#X connect 34 0 33 1;
+#X connect 35 0 33 1;
+#X connect 41 0 9 0;
+#X connect 46 0 0 0;
+#X connect 47 0 9 0;
+#X connect 48 0 6 0;
+#X connect 48 0 27 0;
+#X connect 48 1 6 1;
+#X connect 48 2 49 0;
+#X connect 54 0 60 0;
+#X connect 55 0 68 0;
+#X connect 56 0 68 0;
+#X connect 57 0 68 0;
+#X connect 58 0 68 0;
+#X connect 59 0 68 0;
+#X connect 60 0 55 0;
+#X connect 65 0 68 0;
+#X connect 66 0 68 0;
+#X connect 68 0 51 0;
+#X connect 68 1 52 0;
+#X connect 68 2 69 0;
diff --git a/mp3live~/interface.h b/mp3live~/interface.h
new file mode 100644
index 0000000..de3136a
--- /dev/null
+++ b/mp3live~/interface.h
@@ -0,0 +1,32 @@
+/*
+** Copyright (C) 2000 Albert L. Faber
+**  
+** 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.
+*/
+
+#ifndef INTERFACE_H_INCLUDED
+#define INTERFACE_H_INCLUDED
+
+// #include "common.h"
+#include "interface.h"
+
+BOOL InitMP3(PMPSTR mp);
+int	 decodeMP3(PMPSTR mp,unsigned char *inmemory,int inmemsize,char *outmemory,int outmemsize,int *done);
+void ExitMP3(PMPSTR mp);
+
+/* added remove_buf to support mpglib seeking */
+void remove_buf(PMPSTR mp);
+
+#endif
diff --git a/mp3live~/mp3fileout~.c b/mp3live~/mp3fileout~.c
new file mode 100644
index 0000000..edadf8e
--- /dev/null
+++ b/mp3live~/mp3fileout~.c
@@ -0,0 +1,553 @@
+/* ------------------------ mp3fileout~ --------------------------------------- */
+/*                                                                              */
+/* Tilde object to send an mp3 file to a peer using mp3streamin~                */
+/* Written by Yves Degoyon (ydegoyon@free.fr).                                  */
+/* Tarballs and updates @ http://ydegoyon.free.fr                               */
+/*                                                                              */
+/* 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.                             */
+/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can       */
+/* be found at http://www.cdex.n3.net.                                          */
+/*                                                                              */
+/* "See mass murder on a scale you've never seen"                                */
+/* "And all the one who tried hard to succeed"                                   */
+/* You know who, don't you ???                                                  */
+/* ---------------------------------------------------------------------------- */
+                                                                                     
+
+#include <m_imp.h>
+#include <g_canvas.h>
+
+#include <sys/types.h>
+#include <string.h>
+#ifdef UNIX
+#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>
+#include "mpg123.h"      /* mpg123 decoding library from lame 3.92 */
+#include "mpglib.h"      /* mpglib decoding library from lame 3.92 */
+#include "interface.h"   /* mpglib decoding library from lame 3.92 */
+#define SOCKET_ERROR -1
+#else
+#include <winsock.h>
+#endif
+
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#define INPUT_BUFFER_SIZE 32768
+#define OUTPUT_BUFFER_SIZE 32768
+#define MAX_FRAME_SIZE 1152
+
+/* useful debugging functions from mpglib */
+extern int decode_header( struct frame* fr, unsigned long newhead );
+extern void print_header_compact( struct frame* fr );
+extern int head_check( unsigned long head, int check_layer );
+
+/* time-out used for select() call */
+static struct timeval ztout;
+
+static char   *mp3fileout_version = "mp3fileout~: mp3 file streamer version 0.2, written by ydegoyon@free.fr";
+
+extern void sys_sockerror(char *s);
+
+void mp3fileout_closesocket(int fd)
+{
+#ifdef UNIX
+    if ( close(fd) < 0 )
+    {
+       perror( "close" );
+    }
+    else
+    {
+       post( "mp3fileout~ : closed socket : %d", fd );
+    }
+#endif
+#ifdef NT
+    closesocket(fd);
+#endif
+    sys_rmpollfn(fd);
+}
+
+/* ------------------------ mp3fileout~ ----------------------------- */
+
+static t_class *mp3fileout_class;
+
+typedef struct _mp3fileout
+{
+     t_object x_obj;
+     t_int x_socket;
+     t_int x_fd;         /* file descriptor for the mp3 file */
+     t_int x_eof;        /* end of file is reached           */
+     t_int x_emit;       /* indicates the ability to emit    */
+     t_int x_nbwaitloops;/* synchronization cycles count     */
+     t_int x_blocksize;  /* actual blocksize                 */
+
+     void *x_inbuffer;   /* accumulation buffer for read mp3 frames */
+     t_int x_inwriteposition;
+     t_int x_inbuffersize;
+     t_int x_framesize;
+     t_int x_offset;     /* offset used for decoding                    */
+     t_int x_nbloops;    /* number of perform loops                     */
+
+     void *x_outbuffer;   /* buffer to be emitted */       
+     t_int x_outframes;   /* number of frames emitted */
+     t_int x_outbuffersize;
+     t_int x_outavable;   /* number of available bytes to emit */
+
+     t_canvas *x_canvas;                
+
+     t_outlet *x_connected; /* indicates state of the connection */
+     t_outlet *x_endreached;/* indicates the end of file         */
+     t_outlet *x_frames;    /* indicates the number of frames emitted */
+
+} t_mp3fileout;
+
+static int mp3fileout_search_header(t_mp3fileout *x)
+{
+  t_int i;
+  t_int length = 0;
+  struct frame hframe;
+  unsigned long cheader;
+  t_int ret = sizeof( unsigned long);
+  t_int foffset = 0;
+  unsigned int a,b,c,d;
+  unsigned char buf[sizeof(unsigned long)];
+  t_float nbsamplesframe = 0;
+
+  while( ret>0 )
+  {
+    ret = read( x->x_fd, (void *)buf, sizeof( unsigned long ) );
+    
+    foffset+=ret;
+
+    if ( ret>0 ) 
+    {
+      /* check for a valid header */
+      a = buf[0];
+      b = buf[1];
+      c = buf[2];
+      d = buf[3];
+
+      cheader = 0;
+      cheader = a;
+      cheader <<= 8;
+      cheader |= b;
+      cheader <<= 8;
+      cheader |= c;
+      cheader <<= 8;
+      cheader |= d; 
+      if ( head_check( cheader, 0 ) )
+      {
+        decode_header( &hframe, cheader );
+        // print_header_compact( &hframe );
+        x->x_framesize = hframe.framesize;
+        nbsamplesframe = ( hframe.mpeg25 ? 576 : 1152 );
+        x->x_nbwaitloops = (int)(nbsamplesframe/x->x_blocksize);
+        if ( x->x_nbwaitloops == 0 ) x->x_nbwaitloops = 1;
+        // post ( "mp3fileout~ : will wait %d loops", x->x_nbwaitloops );
+
+        // rewind file to the start of the frame
+        if ( lseek( x->x_fd, -sizeof(unsigned long), SEEK_CUR ) < 0 )
+        {
+          post( "mp3fileout~ : could not rewind file." );
+        }
+        if ( x->x_outframes == 0 ) 
+        {
+            post( "mp3fileout~ : found firstframe @ %d", foffset );
+        }
+        break;
+      }
+      // post( "mp3fileout~ : read %d bytes.", ret );
+    } 
+    else
+    {
+      if ( ret < 0 )
+      {
+         post( "mp3fileout~ : error encountered ( ret=%d )...file reading done.", ret );
+         perror( "read" );
+         x->x_eof = 1;
+      }
+      else
+      {
+         post( "mp3fileout~ : file reading done.", ret );
+         x->x_eof = 1;
+         outlet_bang( x->x_endreached );
+      } 
+      return -1;
+    }
+
+   }
+
+   return x->x_framesize;
+}
+
+static int mp3fileout_read_frame(t_mp3fileout *x)
+{
+  int size, ret;
+
+   if ( x->x_fd > 0 && !x->x_eof)
+   {
+      if ( ( size = mp3fileout_search_header( x ) ) > 0 )
+      {
+         if ( size+sizeof(unsigned long) >  INPUT_BUFFER_SIZE )
+         {
+            post( "mp3fileout~ : cannot read frame : size too big : %d", size );
+            return -1;
+         }
+         // post( "mp3fileout~ : reading a frame : size : %d", size );
+         ret = read( x->x_fd, x->x_inbuffer, size+sizeof(unsigned long) );
+         
+         if ( ret>0 )
+         {
+            memcpy( x->x_outbuffer, x->x_inbuffer, ret );
+            x->x_outavable += ret;
+            return ret;
+         }
+         else
+         {
+            return -1;
+         }
+      }
+      else
+      {
+         return -1;
+      }
+   }
+   else
+   {
+      return -1;
+   }
+}
+
+static int mp3fileout_send_frame(t_mp3fileout *x)
+{
+  int ret=0;
+
+    if ( x->x_socket > 0 && x->x_emit )
+    {
+       if ( ( ret = send( x->x_socket, x->x_outbuffer, x->x_outavable, MSG_NOSIGNAL ) ) < 0 )
+       {
+          post( "mp3fileout~ : connection lost." );
+          perror( "send" );
+          x->x_socket = -1;
+          x->x_emit = 0;
+          return -1;
+       }
+       else
+       {
+          memcpy( x->x_outbuffer, x->x_outbuffer+ret, x->x_outbuffersize-ret );
+          x->x_outavable -= ret;
+          x->x_outframes++;
+          outlet_float( x->x_frames, x->x_outframes );
+          // post( "mp3fileout~ : sent %d bytes, x->x_outavable : %d", ret, x->x_outavable );
+       }
+
+    } 
+    else
+    {
+       // artificially empty buffer
+       x->x_outavable = 0;
+    }
+    return ret;
+}
+
+static void mp3fileout_free(t_mp3fileout *x)
+{
+     if (x->x_socket > 0) {
+        post( "mp3fileout~ : closing socket" );
+        mp3fileout_closesocket(x->x_socket);
+        x->x_socket = -1;
+     }
+     if ( x->x_fd > 0 )
+     {
+       if ( close( x->x_fd ) < 0 )
+       {
+          post( "mp3fileout~ : could not close file." );
+          perror( "close" );
+       }
+     }
+     if ( x->x_inbuffer ) freebytes( x->x_inbuffer, x->x_inbuffersize );
+}
+
+static t_int *mp3fileout_perform(t_int *w)
+{
+     t_mp3fileout *x = (t_mp3fileout*) (w[1]);
+     int ret;
+     int i = 0;
+
+     x->x_blocksize = (t_int)(w[2]);
+     // check new incoming data
+     if ( x->x_socket > 0 )
+     {
+        if ( x->x_nbloops % x->x_nbwaitloops == 0 )
+        {
+           /* read a frame in the file */            
+           if ( mp3fileout_read_frame(x) > 0 )
+           {
+             /* send the frame to the peer */          
+             mp3fileout_send_frame(x);
+           }
+        }
+        x->x_nbloops = ( x->x_nbloops+1 ) % x->x_nbwaitloops;
+     }
+     return (w+3);
+}
+
+static void mp3fileout_dsp(t_mp3fileout *x, t_signal **sp)
+{
+    dsp_add(mp3fileout_perform, 2, x, sp[0]->s_n);
+}
+
+    /* start streaming */               
+static void mp3fileout_start(t_mp3fileout *x)
+{
+    x->x_emit = 1;
+    if ( x->x_fd > 0 )
+    {
+      // reset file pointer
+      if ( lseek( x->x_fd, 0, SEEK_SET ) < 0 )
+      {
+           post ( "mp3fileout~ : could not reset file pointer.");
+           x->x_eof = 1;
+           return;
+      }
+      x->x_eof = 0;
+      x->x_outframes = 0;
+      outlet_float( x->x_frames, x->x_outframes );
+    }
+}
+
+    /* resume file reading */               
+static void mp3fileout_resume(t_mp3fileout *x)
+{
+    x->x_emit = 1;
+}
+
+    /* seek in  file */
+static void mp3fileout_seek(t_mp3fileout *x, t_floatarg foffset)
+{
+    if ( foffset < 0 )
+    {
+       post( "mp3fileout~ : wrong offset.");
+       return;
+    }
+    if ( x->x_fd > 0 )
+    {
+      // reset file pointer
+      if ( lseek( x->x_fd, (int)foffset, SEEK_SET ) < 0 )
+      {
+           post ( "mp3fileout~ : could not reset file pointer.");
+           x->x_eof = 1;
+           return;
+      }
+      x->x_eof = 0;
+    }
+}
+
+    /* stop streaming */               
+static void mp3fileout_stop(t_mp3fileout *x)
+{
+    x->x_emit = 0;
+}
+
+    /* open mp3 file */                 
+static void mp3fileout_open(t_mp3fileout *x, t_symbol *filename)
+{
+    // first close previous file 
+    if ( x->x_fd > 0 )
+    {
+       if ( close( x->x_fd ) < 0 )
+       {
+          post( "mp3fileout~ : could not close file." );
+          perror( "close" );
+       }
+       x->x_outframes = 0;
+       outlet_float( x->x_frames, x->x_outframes );
+    }
+    if ( ( x->x_fd = open( filename->s_name, O_RDONLY ) ) < 0 )
+    {
+       post( "mp3fileout~ : could not open file : %s", filename->s_name );
+       perror( "open" );
+       x->x_eof = 1;
+    }
+    else
+    {
+       x->x_eof = 0;
+       post( "mp3fileout~ : opened file : %s ( fd = %d )", filename->s_name, x->x_fd );
+    }
+}
+
+    /* connect to the peer         */
+static void mp3fileout_connect(t_mp3fileout *x, t_symbol *hostname, t_floatarg fportno)
+{
+    struct          sockaddr_in csocket;
+    struct          hostent *hp;
+    int             portno            = fportno;    /* get port from message box */
+ 
+        /* variables used for communication with the peer */
+    unsigned int    len;
+    int    sockfd;
+ 
+#ifndef UNIX
+    unsigned int    ret;
+#else
+    int    ret;
+#endif
+ 
+    if (x->x_socket >= 0)
+    {
+        error("mp3fileout~: already connected");
+        return;
+    }
+ 
+    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (sockfd < 0)
+    {
+        error("mp3fileout~: internal error while attempting to open socket");
+        return;
+    }
+                                                         
+        /* connect socket using hostname provided in command line */
+    csocket.sin_family = AF_INET;
+    hp = gethostbyname(hostname->s_name);
+    if (hp == 0)
+    {
+        post("mp3fileout~: bad host?");
+#ifndef UNIX
+        closesocket(sockfd);
+#else
+        close(sockfd);
+#endif
+        return;
+    }
+    memcpy((char *)&csocket.sin_addr, (char *)hp->h_addr, hp->h_length);
+ 
+        /* assign client port number */
+    csocket.sin_port = htons((unsigned short)portno);
+ 
+        /* try to connect.  */
+    post("mp3fileout~: connecting to port %d", portno);
+    if (connect(sockfd, (struct sockaddr *) &csocket, sizeof (csocket)) < 0)
+    {
+        error("mp3fileout~: connection failed!\n");
+#ifndef UNIX
+        closesocket(sockfd);
+#else
+        close(sockfd);
+#endif
+        return;
+    }
+ 
+    x->x_socket = sockfd;
+    x->x_outframes = 0;
+    outlet_float( x->x_frames, x->x_outframes );
+    outlet_float( x->x_connected, 1 );         
+    post( "mp3fileout~ : connected to peer" );
+ 
+}  
+
+    /* close connection to the peer         */
+static void mp3fileout_disconnect(t_mp3fileout *x)
+{
+ 
+    int err = -1;
+    if(x->x_socket >= 0)            /* close socket */
+    {
+#ifndef UNIX
+        closesocket(x->x_socket);
+#else
+        close(x->x_socket);
+#endif
+        x->x_socket = -1;
+        outlet_float( x->x_connected, 0 );
+        x->x_outframes = 0;
+        outlet_float( x->x_frames, x->x_outframes );
+        post("mp3fileout~: connection closed");
+    }
+}
+
+static void *mp3fileout_new(void)
+{
+    t_mp3fileout *x;
+    int i;
+    
+    x = (t_mp3fileout *)pd_new(mp3fileout_class);
+    x->x_connected = outlet_new( &x->x_obj, &s_float ); 
+    x->x_frames = outlet_new( &x->x_obj, &s_float ); 
+    x->x_endreached = outlet_new( &x->x_obj, &s_bang ); 
+    
+    x->x_socket = -1;
+    x->x_fd = -1;
+    x->x_eof = 0;
+    x->x_canvas = canvas_getcurrent();
+
+    x->x_offset = 0;
+    x->x_inbuffersize = INPUT_BUFFER_SIZE;
+    x->x_inbuffer = (char*) getbytes( x->x_inbuffersize );
+    if ( !x->x_inbuffer )
+    {
+       post( "mp3fileout~ : could not allocate buffers." );
+       return NULL;
+    }
+    memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE );
+
+    x->x_outbuffersize = OUTPUT_BUFFER_SIZE;
+    x->x_outbuffer = (char*) getbytes( x->x_outbuffersize );
+    if ( !x->x_outbuffer )
+    {
+       post( "mp3fileout~ : could not allocate buffers." );
+       return NULL;
+    }
+    memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE );
+    x->x_outavable = 0;
+
+    x->x_inwriteposition = 0;
+    x->x_nbloops = 0;
+    x->x_nbwaitloops = 1;
+
+    return (x);
+}
+
+void mp3fileout_tilde_setup(void)
+{
+    post( mp3fileout_version );
+    mp3fileout_class = class_new(gensym("mp3fileout~"), 
+    	(t_newmethod) mp3fileout_new, (t_method) mp3fileout_free,
+    	sizeof(t_mp3fileout),  0, A_NULL);
+
+    class_addmethod(mp3fileout_class, nullfn, gensym("signal"), 0);
+    class_addmethod(mp3fileout_class, (t_method) mp3fileout_dsp, gensym("dsp"), 0);
+    class_addmethod(mp3fileout_class, (t_method)mp3fileout_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0);
+    class_addmethod(mp3fileout_class, (t_method)mp3fileout_open, gensym("open"), A_SYMBOL, 0);
+    class_addmethod(mp3fileout_class, (t_method)mp3fileout_disconnect, gensym("disconnect"), 0);
+    class_addmethod(mp3fileout_class, (t_method)mp3fileout_start, gensym("start"), 0);
+    class_addmethod(mp3fileout_class, (t_method)mp3fileout_resume, gensym("resume"), 0);
+    class_addmethod(mp3fileout_class, (t_method)mp3fileout_seek, gensym("seek"), A_DEFFLOAT, 0);
+    class_addmethod(mp3fileout_class, (t_method)mp3fileout_stop, gensym("stop"), 0);
+    class_sethelpsymbol(mp3fileout_class, gensym("help-mp3live~.pd"));
+}
diff --git a/mp3live~/mp3streamin~.c b/mp3live~/mp3streamin~.c
new file mode 100644
index 0000000..954af64
--- /dev/null
+++ b/mp3live~/mp3streamin~.c
@@ -0,0 +1,665 @@
+/* ------------------------ mp3streamin~ -------------------------------------- */
+/*                                                                              */
+/* Tilde object to receive an mp3-stream sent by a peer using mp3streamout~.    */
+/* Written by Yves Degoyon (ydegoyon@free.fr).                                  */
+/* Tarballs and updates @ http://ydegoyon.free.fr                               */
+/*                                                                              */
+/* 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.                             */
+/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can       */
+/* be found at http://www.cdex.n3.net.                                          */
+/*                                                                              */
+/* "Repackage sex, your interests."                                              */
+/* "Somehow, maintain the interest."                                             */
+/* Gang Of Four -- Natural's Not In It                                          */
+/* ---------------------------------------------------------------------------- */
+                                                                                     
+
+#include <m_imp.h>
+#include <g_canvas.h>
+
+#include <sys/types.h>
+#include <string.h>
+#ifdef UNIX
+#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>
+#include "mpg123.h"      /* mpg123 decoding library from lame 3.92 */
+#include "mpglib.h"      /* mpglib decoding library from lame 3.92 */
+#include "interface.h"   /* mpglib decoding library from lame 3.92 */
+#define SOCKET_ERROR -1
+#else
+#include <winsock.h>
+#endif
+
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#define MIN_AUDIO_INPUT 8064 // we must a least have 8 chunks to play a correct sound
+#define INPUT_BUFFER_SIZE MIN_AUDIO_INPUT
+#define OUTPUT_BUFFER_SIZE 131072 /* 128k*/
+#define LAME_AUDIO_CHUNK_SIZE 1152
+#define BARHEIGHT 10
+#define MAX_DECODERS 10 
+
+/* useful debugging functions from mpglib */
+extern int decode_header( struct frame* fr, unsigned long newhead );
+extern void print_header_compact( struct frame* fr );
+extern int head_check( unsigned long head, int check_layer );
+
+/* time-out used for select() call */
+static struct timeval ztout;
+
+static char   *mp3streamin_version = "mp3streamin~: mp3 peer-to-peer streamer version 0.3, written by ydegoyon@free.fr";
+
+extern void sys_sockerror(char *s);
+
+void mp3streamin_closesocket(int fd)
+{
+#ifdef UNIX
+    if ( close(fd) < 0 )
+    {
+       perror( "close" );
+    }
+    else
+    {
+       post( "mp3streamin~ : closed socket : %d", fd );
+    }
+#endif
+#ifdef NT
+    closesocket(fd);
+#endif
+    sys_rmpollfn(fd);
+}
+
+int setsocketoptions(int sockfd)
+{ 
+     int sockopt = 1;
+     if (setsockopt(sockfd, SOL_TCP, TCP_NODELAY, (const char*) &sockopt, sizeof(int)) < 0)
+     {
+	  post("mp3streamin~ : setsockopt TCP_NODELAY failed");
+          perror( "setsockopt" );
+          return -1;
+     }
+     else
+     {
+	  post("mp3streamin~ : TCP_NODELAY set");
+     }
+     
+#ifdef UNIX
+     sockopt = 1;    
+     if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0)
+     {
+	  post("mp3streamin~ : setsockopt SO_REUSEADDR failed");
+          perror( "setsockopt" );
+          return -1;
+     }
+     else
+     {
+	  post("mp3streamin~ : setsockopt SO_REUSEADDR done.");
+     }
+#endif
+     return 0;
+}
+
+
+/* ------------------------ mp3streamin~ ----------------------------- */
+
+static t_class *mp3streamin_class;
+
+typedef struct _mp3streamin
+{
+     t_object x_obj;
+     t_int x_instance;
+     t_int x_socket;
+     t_int x_shutdown;
+     t_outlet *x_connectionip;
+     t_int x_serversocket;
+     t_int x_inpackets;  /* number of packets received */
+     t_int x_dpacket;    /* displayed packet in status bar */
+     t_int x_packetsize; /* size of the packets */
+     t_int x_pblocks;    /* processed blocks */
+     t_int x_graphic;    /* indicates if we show a graphic bar */
+
+     void *x_inbuffer;   /* accumulation buffer for incoming mp3 frames */
+     t_int x_inwriteposition;
+     t_int x_inbuffersize;
+
+     t_float *x_outbuffer;   /* buffer to store audio decoded data */
+     t_int x_outwriteposition;
+     t_int x_outreadposition;
+     t_int x_outunread;
+     t_int x_outbuffersize;
+
+     t_canvas *x_canvas;                
+
+     t_int x_stream;         /* indicates if a stream is connected ( meaning correct input flow ) */
+     t_int x_newstream;      /* at first, the stream must provide enough data to start */             
+     t_int x_bitrateindex;   /* remember the bitrate index */
+
+} t_mp3streamin;
+
+/* too bad, this needs to be static,
+   handling an array to enable several decoders in pd */
+static  MPSTR   mp[MAX_DECODERS];  /* decoder buffer */
+int nbinstances = 0;
+
+void mp3streamin_tilde_mpglib_init(t_mp3streamin *x)
+{
+  int ret;
+
+     InitMP3(&mp[x->x_instance]);
+}
+
+static int mp3streamin_decode_input(t_mp3streamin *x)
+{
+  int i;
+  int alength = 0;
+  struct frame hframe;
+  unsigned int a,b,c,d;
+  unsigned long cheader;
+  static char out[8192];
+  signed short int *p = (signed short int *) out;
+  int     pbytes;
+  int     ret;
+
+   if ( !x->x_shutdown )
+   {
+    /* decode first 4 bytes as the header */
+    a = *((unsigned char*)x->x_inbuffer);
+    b = *((unsigned char*)x->x_inbuffer+1);
+    c = *((unsigned char*)x->x_inbuffer+2);
+    d = *((unsigned char*)x->x_inbuffer+3);
+
+    cheader = 0;
+    cheader = a;
+    cheader <<= 8;
+    cheader |= b;
+    cheader <<= 8;
+    cheader |= c;
+    cheader <<= 8;
+    cheader |= d;
+    if ( head_check( cheader, 0 ) )
+    {
+      // post( "mp3streamin~ : valid header ( packet=%d)", x->x_inpackets );
+      decode_header( &hframe, cheader );
+      // print_header_compact( &hframe );
+      // when the bitrate change, reinit decoder
+      if ( x->x_bitrateindex != hframe.bitrate_index )
+      {
+         ExitMP3(&mp[x->x_instance]);
+         InitMP3(&mp[x->x_instance]);
+         x->x_bitrateindex = hframe.bitrate_index;
+      }
+    } 
+    else
+    {
+      post( "mp3streamin~ : error : mp3 packet received without header" );  
+      // ignore data
+      x->x_inwriteposition = 0; 
+      x->x_inpackets--; 
+      return( -1 );
+    }
+
+    // post( "mp3streamin~ : decoding %d bytes framesize=%d", x->x_inwriteposition, hframe.framesize );
+    ret =
+        decodeMP3(&mp[x->x_instance], (unsigned char*)x->x_inbuffer, 
+                            x->x_inwriteposition, (char *) p, sizeof(out), &pbytes);
+
+    switch (ret) {
+    case MP3_OK:
+        switch (mp[x->x_instance].fr.stereo) {
+        case 1:
+        case 2:
+            alength = ((mp[x->x_instance].fr.stereo==1)?pbytes >> 1 : pbytes >> 2);
+            // post( "mp3streamin~ : processed %d samples", alength );
+            // update outbuffer contents 
+            for ( i=0; i<alength; i++ )
+            {
+              if ( x->x_outunread >= x->x_outbuffersize-2 )
+              {
+                  post( "mp3streamin~ : too much input ... ignored" );
+                  continue;
+              }
+              *(x->x_outbuffer+x->x_outwriteposition) = ((t_float)(*p++))/32767.0;
+              x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize;
+              *(x->x_outbuffer+x->x_outwriteposition) = 
+                     ((mp[x->x_instance].fr.stereo==2)?((t_float)(*p++))/32767.0 : 0.0);
+              x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize;
+              x->x_outunread+=2;
+
+              if ( x->x_outunread > MIN_AUDIO_INPUT && !x->x_stream )
+              {
+                  post( "mp3streamin~ : stream connected." );
+                  x->x_stream = 1;
+              }
+            }
+
+            break;
+        default:
+            alength = -1;
+            break;
+        }
+        break;
+
+    case MP3_NEED_MORE:
+        post( "mp3streamin~ : retry lame decoding (more data needed)." );
+        alength = 0;
+        break;
+
+    case MP3_ERR:
+        post( "mp3streamin~ : lame decoding failed." );
+        alength = -1;
+        break;
+
+    }
+
+    x->x_inwriteposition = 0; 
+   }
+   else
+   {
+     if ( x->x_outunread == 0 )
+     {
+      post( "mp3streamin~ : connection closed" );
+      mp3streamin_closesocket(x->x_socket);
+      x->x_stream = 0;
+      x->x_newstream = 0;
+      x->x_inpackets = 0;
+      x->x_inwriteposition = 0;
+      x->x_bitrateindex = -1;
+      x->x_socket=-1;
+      outlet_symbol( x->x_connectionip, gensym("") );
+     }
+   }
+
+   if ( x->x_graphic && glist_isvisible( x->x_canvas ) )
+   {
+         /* update graphical read status */
+     if ( x->x_inpackets != x->x_dpacket ) 
+     { 
+        char color[32];
+        int minpackets = ( MIN_AUDIO_INPUT/LAME_AUDIO_CHUNK_SIZE )-2; // audio loop has eaten some already
+
+
+            sys_vgui(".x%x.c delete rectangle %xSTATUS\n", x->x_canvas, x );
+            sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x );
+            if ( x->x_outunread > 0 )
+            {
+             t_int width;
+
+              if ( x->x_inpackets < (MIN_AUDIO_INPUT/LAME_AUDIO_CHUNK_SIZE)/2 )
+              {
+               strcpy( color, "red" );
+              }
+              else
+              {
+               strcpy( color, "lightgreen" );
+              }
+              width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) );
+              sys_vgui(".x%x.c create rectangle %d %d %d %d -fill %s -tags %xSTATUS\n",
+                  x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1,
+                  x->x_obj.te_xpix+(x->x_inpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, 
+                  x->x_obj.te_ypix - 1, color, x );
+              sys_vgui(".x%x.c create line %d %d %d %d -fill red -tags %xTHRESHOLD\n",
+                  x->x_canvas, x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, 
+                  x->x_obj.te_ypix-BARHEIGHT-1,
+                  x->x_obj.te_xpix+(minpackets*x->x_packetsize*width)/INPUT_BUFFER_SIZE, 
+                  x->x_obj.te_ypix-1, x );
+              x->x_dpacket = x->x_inpackets;
+            }
+            else
+            {
+              if ( x->x_shutdown )
+              {
+                 x->x_shutdown=0;
+                 sys_vgui(".x%x.c delete rectangle %xPBAR\n", x->x_canvas, x );
+                 sys_vgui(".x%x.c delete line %xTHRESHOLD\n", x->x_canvas, x );
+              }
+            }
+     }
+   }
+   return alength;
+}
+
+static void mp3streamin_recv(t_mp3streamin *x)
+{
+   int ret;
+
+     if ( ( ret = recv(x->x_socket, (void*) (x->x_inbuffer + x->x_inwriteposition), 
+                (size_t)((x->x_inbuffersize-x->x_inwriteposition)), 
+                MSG_NOSIGNAL) ) < 0 )
+     {
+        post( "mp3_streamin~ : receive error" );
+        perror( "recv" );
+        return; 
+     }
+     else
+     {
+        // post( "streamin~ : received %d bytes at %d on %d ( up to %d)", 
+        //        ret, x->x_inwriteposition, x->x_socket,
+        //        x->x_inbuffersize-x->x_inwriteposition*sizeof( unsigned long) );
+
+        if ( ret == 0 ) 
+        {
+           /* initiate the shutdown phase */
+           x->x_shutdown=1;
+        }
+        else
+        { 
+           // check we don't overflow input buffer
+           if ( (x->x_inpackets+1)*x->x_packetsize > x->x_inbuffersize )
+           {
+              post( "mp3streamin~ : too much input...resetting" );
+              x->x_inpackets=0;
+              x->x_inwriteposition=0;
+              return;
+           }
+           x->x_inpackets++;
+           x->x_packetsize=ret;
+           if ( x->x_inpackets % 100 == 0 )
+           {
+              // post( "mp3streamin~ : received %d packets", x->x_inpackets );
+           }
+           x->x_inwriteposition += ret;
+        }
+             
+        mp3streamin_decode_input(x);
+     }
+}
+
+static void mp3streamin_acceptconnection(t_mp3streamin *x)
+{
+    struct sockaddr_in incomer_address;
+    int sockaddrl = (int) sizeof( struct sockaddr );
+
+    int fd = accept(x->x_serversocket, (struct sockaddr*)&incomer_address, &sockaddrl );
+
+    if (fd < 0) {
+	 post("mp3streamin~: accept failed");
+	 return;
+    }
+
+    if (x->x_socket > 0) {
+         sys_addpollfn(fd, (t_fdpollfn)mp3streamin_recv, x);
+         if ( x->x_outunread != 0 )
+         {
+	   post("mp3streamin~: still have some data to decode, retry later you %s.", 
+                 inet_ntoa( incomer_address.sin_addr ));
+           mp3streamin_closesocket( fd );
+           return;
+         }
+	 post("mp3streamin~: the source has changed to %s.", 
+               inet_ntoa( incomer_address.sin_addr ));
+	 mp3streamin_closesocket(x->x_socket);
+    }
+
+    x->x_socket = fd;
+    sys_addpollfn(x->x_socket, (t_fdpollfn)mp3streamin_recv, x);
+    outlet_symbol( x->x_connectionip, gensym( inet_ntoa( incomer_address.sin_addr) ) );
+
+    if ( x->x_graphic && glist_isvisible( x->x_canvas ) )
+    {
+      t_int width;
+ 
+       width = rtext_width( glist_findrtext( (t_glist*)x->x_canvas, (t_text *)x ) );
+       sys_vgui(".x%x.c create rectangle %d %d %d %d -fill lightblue -tags %xPBAR\n",
+              x->x_canvas, x->x_obj.te_xpix, x->x_obj.te_ypix-BARHEIGHT-1,
+                  x->x_obj.te_xpix + width, x->x_obj.te_ypix - 1, x );
+    }
+    x->x_stream = 0;
+    x->x_newstream = 1;
+
+}
+
+
+static int mp3streamin_startservice(t_mp3streamin* x, int portno)
+{
+    struct sockaddr_in server;
+    int sockfd;
+
+    /* create a socket */
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+    if (sockfd < 0)
+    {
+    	sys_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);
+
+    setsocketoptions(sockfd);
+
+    /* name the socket */
+    if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
+	 sys_sockerror("bind");
+	 mp3streamin_closesocket(sockfd);
+	 return (0);
+    }
+
+    if (listen(sockfd, 5) < 0) {
+      sys_sockerror("listen");
+      mp3streamin_closesocket(sockfd);
+    }
+    else 
+    {
+      x->x_serversocket = sockfd;
+      sys_addpollfn(x->x_serversocket, (t_fdpollfn)mp3streamin_acceptconnection, x);
+    }
+    
+    return 1;
+}
+
+static void mp3streamin_free(t_mp3streamin *x)
+{
+     post( "mp3streamin~ : free %x", x );
+     if (x->x_serversocket > 0) {
+        post( "mp3streamin~ : closing server socket" );
+	mp3streamin_closesocket(x->x_serversocket);
+        x->x_serversocket = -1;
+     }
+     if (x->x_socket > 0) {
+        post( "mp3streamin~ : closing socket" );
+        mp3streamin_closesocket(x->x_socket);
+        x->x_socket = -1;
+     }
+     if ( x->x_inbuffer ) freebytes( x->x_inbuffer, x->x_inbuffersize );
+     if ( x->x_outbuffer ) freebytes( x->x_outbuffer, x->x_outbuffersize*sizeof(t_float) );
+     if ( x->x_instance == nbinstances-1 )
+     {
+        nbinstances--;
+     }
+}
+
+static t_int *mp3streamin_perform(t_int *w)
+{
+     t_mp3streamin *x = (t_mp3streamin*) (w[1]);
+     t_float *out1 = (t_float *)(w[2]);
+     t_float *out2 = (t_float *)(w[3]);
+     int n = (int)(w[4]);
+     int bsize = n;
+     int ret;
+     int i = 0;
+
+     while( n-- )
+     {
+         if ( ( ( x->x_outunread > MIN_AUDIO_INPUT ) && x->x_newstream ) || // wait the buffer to load
+              ( ( x->x_shutdown ) && ( x->x_outunread >= 2 ) ) ||  // clean disconnection
+              ( x->x_stream ) // check that the stream provides enough data
+            )
+         {
+            if ( x->x_newstream && !x->x_shutdown )
+            {
+               x->x_newstream = 0;
+               x->x_stream = 1;
+            }
+            *out1++=*(x->x_outbuffer+x->x_outreadposition);
+            x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize;
+            *out2++=*(x->x_outbuffer+x->x_outreadposition);
+            x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize;
+            x->x_outunread-=2;
+            if ( n == 1 ) x->x_pblocks++;
+         }
+         else
+         {
+            *out1++=0.0;
+            *out2++=0.0;
+         }
+     }
+
+     if ( ( x->x_outunread <= MIN_AUDIO_INPUT/10  ) && ( x->x_stream ) )
+     {
+           post( "mp3streamin~ : stream lost (too little input)" );
+           x->x_stream = 0;
+           x->x_newstream = 1; // waiting for a new stream
+     }
+
+     if ( x->x_pblocks == LAME_AUDIO_CHUNK_SIZE/bsize ) 
+     {
+        x->x_inpackets--;
+        x->x_pblocks = 0;
+     }
+
+#ifdef DO_MY_OWN_SELECT
+     // check new incoming data
+     if ( x->x_socket > 0 )
+     {
+       fd_set readset;
+       fd_set exceptset;
+
+         FD_ZERO(&readset);
+         FD_ZERO(&exceptset);
+         FD_SET(x->x_socket, &readset );
+         FD_SET(x->x_socket, &exceptset );
+
+         if ( select( maxfd+1, &readset, NULL, &exceptset, &ztout ) >0 )
+         {
+           if ( FD_ISSET( x->x_socket, &readset) || FD_ISSET( x->x_socket, &exceptset ) )
+           {
+              /* receive data or error and decode it */
+              mp3streamin_recv(x);
+           }
+         }
+     }
+#endif
+     return (w+5);
+}
+
+static void mp3streamin_dsp(t_mp3streamin *x, t_signal **sp)
+{
+    dsp_add(mp3streamin_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+}
+
+
+static void *mp3streamin_new(t_floatarg fportno, t_floatarg fdographics)
+{
+    t_mp3streamin *x;
+    int i;
+    
+    if ( fportno < 0 || fportno > 65535 )
+    {
+       post( "mp3streamin~ : error : wrong portnumber : %d", (int)fportno );
+       return NULL;
+    }
+    if ( ((int)fdographics != 0) && ((int)fdographics != 1.) )
+    {
+       post( "mp3streamin~ : error : constructor : mp3streamin~ <portnumber> [graphic flag = 0 | 1 ] ( got = %f)", fdographics );
+       return NULL;
+    }
+
+    x = (t_mp3streamin *)pd_new(mp3streamin_class);
+    post( "mp3streamin~ : new %x (instance = %d) %d", x, nbinstances, sizeof( MPSTR ) );
+    outlet_new(&x->x_obj, &s_signal);
+    outlet_new(&x->x_obj, &s_signal);
+    x->x_connectionip = outlet_new(&x->x_obj, &s_symbol);
+    
+    x->x_serversocket = -1;
+    x->x_socket = -1;
+    x->x_shutdown = 0;
+    x->x_inpackets = 0;
+    x->x_dpacket = -1;
+
+    x->x_canvas = canvas_getcurrent();
+
+    x->x_inbuffersize = INPUT_BUFFER_SIZE;
+    x->x_outbuffersize = OUTPUT_BUFFER_SIZE; 
+    x->x_inbuffer = (char*) getbytes( x->x_inbuffersize );
+    memset( x->x_inbuffer, 0x0, INPUT_BUFFER_SIZE );
+    x->x_outbuffer = (t_float*) getbytes( x->x_outbuffersize*sizeof(t_float) );
+    memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE );
+
+    if ( !x->x_inbuffer || !x->x_outbuffer )
+    {
+       post( "mp3streamin~ : could not allocate buffers." );
+       return NULL;
+    }
+
+    if ( nbinstances < MAX_DECODERS ) 
+    {
+       x->x_instance = nbinstances++;
+    }
+    else
+    {
+       post( "mp3streamin~ : cannot create more decoders (memory issues), sorry" );
+       return NULL;
+    }
+
+    x->x_inwriteposition = 0;
+    x->x_outreadposition = 0;
+    x->x_outwriteposition = 0;
+    x->x_outunread = 0;
+    
+    ztout.tv_sec = 0;
+    ztout.tv_usec = 0;
+
+    x->x_graphic = (int)fdographics;
+
+    post( "mp3streamin~ : starting service on port %d", (int)fportno );
+    mp3streamin_startservice(x, (int)fportno);
+
+    // init lame decoder
+    mp3streamin_tilde_mpglib_init(x);
+
+    return (x);
+}
+
+
+void mp3streamin_tilde_setup(void)
+{
+    post( mp3streamin_version );
+    mp3streamin_class = class_new(gensym("mp3streamin~"), 
+    	(t_newmethod) mp3streamin_new, (t_method) mp3streamin_free,
+    	sizeof(t_mp3streamin),  CLASS_NOINLET, A_DEFFLOAT, A_DEFFLOAT, A_NULL);
+
+    class_addmethod(mp3streamin_class, nullfn, gensym("signal"), 0);
+    class_addmethod(mp3streamin_class, (t_method) mp3streamin_dsp, gensym("dsp"), 0);
+    class_sethelpsymbol(mp3streamin_class, gensym("help-mp3live~.pd"));
+}
diff --git a/mp3live~/mp3streamout~.c b/mp3live~/mp3streamout~.c
new file mode 100644
index 0000000..2bf561f
--- /dev/null
+++ b/mp3live~/mp3streamout~.c
@@ -0,0 +1,733 @@
+/* ------------------------ mp3streamout~ ------------------------------------- */
+/*                                                                              */
+/* Tilde object to send mp3-stream to a peer using mp3streamin~.                */
+/* Written by Yves Degoyon (ydegoyon@free.fr).                                  */
+/* Tarballs and updates @ http://ydegoyon.free.fr                               */
+/*                                                                              */
+/* 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.                             */
+/* Uses the LAME MPEG 1 Layer 3 encoding library (lame_enc.dll) which can       */
+/* be found at http://www.cdex.n3.net.                                          */
+/*                                                                              */
+/* "I'd sell my soul to god"                                                    */
+/* "If it could take away the pain."                                            */
+/* Theo Hakola --                                                               */
+/* ---------------------------------------------------------------------------- */
+
+
+
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <malloc.h>
+#include <ctype.h>
+#ifdef UNIX
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <time.h>
+#include <sys/time.h>
+#include <lame/lame.h>        /* lame encoder stuff */
+#define SOCKET_ERROR -1
+#else
+#include <io.h>
+#include <windows.h>
+#include <winsock.h>
+#include <windef.h>
+#include "lame_enc.h"        /* lame encoder stuff */
+#endif
+
+#include "m_pd.h"            /* standard pd stuff */
+
+#include "mpg123.h"           /* sub-library MPGLIB included in lame */
+/* useful debugging functions from mpglib */
+extern int decode_header( struct frame* fr, unsigned long newhead );
+extern void print_header_compact( struct frame* fr );
+extern int head_check( unsigned long head, int check_layer );
+
+#define        MY_MP3_MALLOC_IN_SIZE        65536
+                                            /* max size taken from lame readme */
+#define        MY_MP3_MALLOC_OUT_SIZE       1.25*MY_MP3_MALLOC_IN_SIZE+7200 
+
+#define        MAXDATARATE 320        /* maximum mp3 data rate is 320kbit/s */
+#define        STRBUF_SIZE 32
+
+static char   *mp3streamout_version = "mp3streamout~: mp3 peer-to-peer streamer version 0.3, written by ydegoyon@free.fr";
+
+#ifndef UNIX
+static        HINSTANCE           dll             = NULL;
+static        BEINITSTREAM        initStream      = NULL;
+static        BEENCODECHUNK       encodeChunk     = NULL;
+static        BEDEINITSTREAM      deinitStream    = NULL;
+static        BECLOSESTREAM       closeStream     = NULL;
+static        BEVERSION           dllVersion      = NULL;
+static        BEWRITEVBRHEADER    writeVBRHeader  = NULL;
+#endif
+
+static t_class *mp3streamout_class;
+
+typedef struct _mp3streamout
+{
+    t_object x_obj;
+
+        /* LAME stuff */
+    int x_lame;               /* info about encoder status */
+    int x_lamechunk;          /* chunk size for LAME encoder */
+    int x_mp3size;            /* number of returned mp3 samples */
+
+        /* buffer stuff */
+    unsigned short x_inp;     /* in position for buffer */
+    unsigned short x_outp;    /* out position for buffer*/
+    short *x_mp3inbuf;        /* data to be sent to LAME */
+    char *x_mp3outbuf;        /* data returned by LAME -> our mp3 stream */
+    short *x_buffer;          /* data to be buffered */
+    int x_bytesbuffered;      /* number of unprocessed bytes in buffer */
+    int x_start;
+
+        /* mp3 format stuff */
+    int x_samplerate;
+    int x_bitrate;            /* bitrate of mp3 stream */
+    int x_mp3mode;            /* mode (mono, joint stereo, stereo, dual mono) */
+    int x_mp3quality;         /* quality of encoding */
+
+        /* connection data        */
+    int x_fd;                 /* info about connection status */
+    int x_outpackets;         /* mp3 packets sent             */
+
+    t_float x_f;              /* float needed for signal input */
+
+#ifdef UNIX
+    lame_global_flags* lgfp;
+#endif
+} t_mp3streamout;
+
+
+    /* encode PCM data to mp3 stream */
+static void mp3streamout_encode(t_mp3streamout *x)
+{
+    unsigned short i, wp;
+    int err = -1;
+    int n = x->x_lamechunk;
+
+#ifdef UNIX
+    if(x->x_lamechunk < (int)sizeof(x->x_mp3inbuf))
+#else
+    if(x->x_lamechunk < sizeof(x->x_mp3inbuf))
+#endif
+    {
+        error("not enough memory!");
+        return;
+    }
+
+        /* on start/reconnect set outpoint that it not interferes with inpoint */ 
+    if(x->x_start == -1)
+    {
+        post("mp3streamout~: initializing buffers");
+            /* we try to keep 2.5 times the data the encoder needs in the buffer */
+        if(x->x_inp > (2 * x->x_lamechunk))
+        {
+            x->x_outp = (short) x->x_inp - (2.5 * x->x_lamechunk);
+        }
+        else if(x->x_inp < (2 * x->x_lamechunk))
+        {
+            x->x_outp = (short) MY_MP3_MALLOC_IN_SIZE - (2.5 * x->x_lamechunk);
+        }
+        x->x_start = 1;
+    }
+    if((unsigned short)(x->x_outp - x->x_inp) < x->x_lamechunk)error("mp3streamout~: buffers overlap!");
+
+    i = MY_MP3_MALLOC_IN_SIZE - x->x_outp;
+
+        /* read from buffer */
+    if(x->x_lamechunk <= i)    
+    {
+            /* enough data until end of buffer */
+        for(n = 0; n < x->x_lamechunk; n++)                                /* fill encode buffer */
+        {
+            x->x_mp3inbuf[n] = x->x_buffer[n + x->x_outp];
+        }
+        x->x_outp += x->x_lamechunk;
+    }
+    else                                        /* split data */
+    {
+        for(wp = 0; wp < i; wp++)                /* data at end of buffer */
+        {
+            x->x_mp3inbuf[wp] = x->x_buffer[wp + x->x_outp];
+        }
+
+        for(wp = i; wp < x->x_lamechunk; wp++)    /* write rest of data at beginning of buffer */
+        {
+            x->x_mp3inbuf[wp] = x->x_buffer[wp - i];
+        }
+        x->x_outp = x->x_lamechunk - i;
+    }
+
+        /* encode mp3 data */
+#ifndef UNIX
+    err = encodeChunk(x->x_lame, x->x_lamechunk, x->x_mp3inbuf, x->x_mp3outbuf, &x->x_mp3size);
+#else
+    x->x_mp3size = lame_encode_buffer_interleaved(x->lgfp, x->x_mp3inbuf, 
+                   x->x_lamechunk/lame_get_num_channels(x->lgfp), 
+                   x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE);
+    x->x_mp3size+=lame_encode_flush( x->lgfp, x->x_mp3outbuf+x->x_mp3size, MY_MP3_MALLOC_OUT_SIZE-x->x_mp3size );
+    // post( "mp3streamout~ : encoding returned %d frames", x->x_mp3size );
+#endif
+
+        /* check result */
+#ifndef UNIX
+    if(err != BE_ERR_SUCCESSFUL)
+    {
+        closeStream(x->x_lame);
+        error("mp3streamout~: lameEncodeChunk() failed (%lu)", err);
+#else
+    if(x->x_mp3size<0)
+    {
+        lame_close( x->lgfp );
+        error("mp3streamout~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size);
+#endif
+        x->x_lame = -1;
+    }
+}
+
+    /* stream mp3 to the peer */
+static void mp3streamout_stream(t_mp3streamout *x)
+{
+    int count = -1, i; 
+    struct frame hframe;
+
+    /* header needs to be included in each packet */
+
+    for( i=0; i<x->x_mp3size; i++ )
+    {
+      // track valid data
+      if ( head_check( *((unsigned long*)x->x_mp3outbuf+i), 3 ) )
+      {
+         // post( "valid header emitted @ %d (byte %d)", i, i*sizeof(unsigned long) );
+      }
+    }
+
+    count = send(x->x_fd, x->x_mp3outbuf, x->x_mp3size, MSG_NOSIGNAL);
+    if(count < 0)
+    {
+        error("mp3streamout~: could not send encoded data to the peer (%d)", count);
+#ifndef UNIX
+        closeStream(x->x_lame);
+#else
+        lame_close( x->lgfp );
+#endif
+        x->x_lame = -1;
+#ifndef UNIX
+        closesocket(x->x_fd);
+#else
+        close(x->x_fd);
+#endif
+        x->x_fd = -1;
+        outlet_float(x->x_obj.ob_outlet, 0);
+    } 
+    else
+    {
+        x->x_outpackets++;
+        if ( x->x_outpackets%100 == 0 )
+        {
+           // post( "mp3streamout~ : emitted %d bytes (packets = %d)", count, x->x_outpackets );
+        }
+    }
+    if((count > 0)&&(count != x->x_mp3size))
+    {
+       error("mp3streamout~: %d bytes skipped", x->x_mp3size - count);
+    }
+}
+
+    
+    /* buffer data as channel interleaved PCM */
+static t_int *mp3streamout_perform(t_int *w)
+{
+    t_float *in1   = (t_float *)(w[1]);       /* left audio inlet */
+    t_float *in2   = (t_float *)(w[2]);       /* right audio inlet */
+    t_mp3streamout *x = (t_mp3streamout *)(w[3]);
+    int n = (int)(w[4]);                      /* number of samples */
+    unsigned short i,wp;
+    float in;
+
+        /* copy the data into the buffer */
+    i = MY_MP3_MALLOC_IN_SIZE - x->x_inp;     /* space left at the end of buffer */
+    
+    n *= 2;                                  /* two channels go into one buffer */
+
+    if( n <= i ) 
+    {
+        /* the place between inp and MY_MP3_MALLOC_IN_SIZE */
+        /* is big enough to hold the data                  */
+
+            for(wp = 0; wp < n; wp++)
+            {
+                if(wp%2)
+                {
+                    in = *(in2++);    /* right channel / inlet */
+                }
+                else
+                {
+                    in = *(in1++);    /* left channel / inlet */
+                }
+                if (in > 1.0) { in = 1.0; }
+                if (in < -1.0) { in = -1.0; }
+                x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in);
+            }
+            x->x_inp += n;    /* n more samples written to buffer */
+    } 
+    else 
+    {
+                /* the place between inp and MY_MP3_MALLOC_IN_SIZE is not */    
+                /* big enough to hold the data                              */
+                /* writing will take place in two turns, one from         */
+                /* x->x_inp -> MY_MP3_MALLOC_IN_SIZE, then from 0 on      */
+
+            for(wp = 0; wp < i; wp++)            /* fill up to end of buffer */
+            {
+                if(wp%2)
+                {
+                    in = *(in2++);
+                }
+                else
+                {
+                    in = *(in1++);
+                }
+                if (in > 1.0) { in = 1.0; }
+                if (in < -1.0) { in = -1.0; }
+                x->x_buffer[wp + x->x_inp] = (short) (32767.0 * in);
+            }
+            for(wp = i; wp < n; wp++)        /* write rest at start of buffer */
+            {
+                if(wp%2)
+                {
+                    in = *(in2++);
+                }
+                else
+                {
+                    in = *(in1++);
+                }
+                if (in > 1.0) { in = 1.0; }
+                if (in < -1.0) { in = -1.0; }
+                x->x_buffer[wp - i] = (short) (32767.0 * in);
+            }
+            x->x_inp = n - i;                /* new writeposition in buffer */
+    }
+
+    if((x->x_fd >= 0)&&(x->x_lame >= 0))
+    { 
+            /* count buffered samples when things are running */
+        x->x_bytesbuffered += n;
+
+            /* encode and send to the peer */
+        if(x->x_bytesbuffered > x->x_lamechunk)
+        {
+            mp3streamout_encode(x);        /* encode to mp3 */
+            mp3streamout_stream(x);        /* stream mp3 to the peer */
+            x->x_bytesbuffered -= x->x_lamechunk;
+        }
+    }
+    else
+    {
+        x->x_start = -1;
+    }
+    return (w+5);
+}
+
+static void mp3streamout_dsp(t_mp3streamout *x, t_signal **sp)
+{
+    dsp_add(mp3streamout_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n);
+}
+
+    /* initialize the lame library */
+static void mp3streamout_tilde_lame_init(t_mp3streamout *x)
+{
+#ifndef UNIX
+        /* encoder related stuff (calculating buffer size) */
+    BE_VERSION    lameVersion        = {0,};                                /* version number of LAME */
+    BE_CONFIG     lameConfig         = {0,};                                /* config structure of LAME */
+    unsigned int    ret;
+#else
+    int    ret;
+    x->lgfp = lame_init(); /* set default parameters for now */
+#endif
+
+#ifndef UNIX
+    /* load lame_enc.dll library */
+
+    dll=LoadLibrary("lame_enc.dll");
+    if(dll==NULL)
+    {
+        error("mp3streamout~: error loading lame_enc.dll");
+        closesocket(x->x_fd);
+        x->x_fd = -1;
+        outlet_float(x->x_obj.ob_outlet, 0);
+        post("mp3streamout~: connection closed");
+        return;
+    }
+
+        /* get Interface functions */
+    initStream      = (BEINITSTREAM) GetProcAddress(dll, TEXT_BEINITSTREAM);
+    encodeChunk     = (BEENCODECHUNK) GetProcAddress(dll, TEXT_BEENCODECHUNK);
+    deinitStream    = (BEDEINITSTREAM) GetProcAddress(dll, TEXT_BEDEINITSTREAM);
+    closeStream     = (BECLOSESTREAM) GetProcAddress(dll, TEXT_BECLOSESTREAM);
+    dllVersion      = (BEVERSION) GetProcAddress(dll, TEXT_BEVERSION);
+    writeVBRHeader  = (BEWRITEVBRHEADER) GetProcAddress(dll,TEXT_BEWRITEVBRHEADER);
+
+        /* check if all interfaces are present */
+    if(!initStream || !encodeChunk || !deinitStream || !closeStream || !dllVersion || !writeVBRHeader)
+    {
+
+        error("mp3streamout~: unable to get LAME interfaces");
+        closesocket(x->x_fd);
+        x->x_fd = -1;
+        outlet_float(x->x_obj.ob_outlet, 0);
+        post("mp3streamout~: connection closed");
+        return;
+    }
+
+        /* get LAME version number */
+    dllVersion(&lameVersion);
+
+    post(   "mp3streamout~: lame_enc.dll version %u.%02u (%u/%u/%u)\n"
+            "            lame_enc engine %u.%02u",    
+            lameVersion.byDLLMajorVersion, lameVersion.byDLLMinorVersion,
+            lameVersion.byDay, lameVersion.byMonth, lameVersion.wYear,
+            lameVersion.byMajorVersion, lameVersion.byMinorVersion);
+
+    memset(&lameConfig,0,sizeof(lameConfig));                        /* clear all fields */
+#else
+    {
+       const char *lameVersion = get_lame_version();
+       post( "mp3streamout~ : using lame version : %s", lameVersion );
+    }
+#endif 
+
+#ifndef UNIX
+
+        /* use the LAME config structure */
+    lameConfig.dwConfig = BE_CONFIG_LAME;
+
+        /* set the mpeg format flags */
+    lameConfig.format.LHV1.dwStructVersion  = 1;
+    lameConfig.format.LHV1.dwStructSize     = sizeof(lameConfig);        
+    lameConfig.format.LHV1.dwSampleRate     = (int)sys_getsr();     /* input frequency - pd's sample rate */
+    lameConfig.format.LHV1.dwReSampleRate   = x->x_samplerate;      /* output s/r - resample if necessary */
+    lameConfig.format.LHV1.nMode            = x->x_mp3mode;         /* output mode */
+    lameConfig.format.LHV1.dwBitrate        = x->x_bitrate;         /* mp3 bitrate */
+    lameConfig.format.LHV1.nPreset          = x->x_mp3quality;      /* mp3 encoding quality */
+    lameConfig.format.LHV1.dwMpegVersion    = MPEG1;                /* use MPEG1 */
+    lameConfig.format.LHV1.dwPsyModel       = 0;                    /* USE DEFAULT PSYCHOACOUSTIC MODEL */
+    lameConfig.format.LHV1.dwEmphasis       = 0;                    /* NO EMPHASIS TURNED ON */
+    lameConfig.format.LHV1.bOriginal        = TRUE;                 /* SET ORIGINAL FLAG */
+    lameConfig.format.LHV1.bCopyright       = TRUE;                 /* SET COPYRIGHT FLAG */
+    lameConfig.format.LHV1.bNoRes           = TRUE;                 /* no bit resorvoir */
+
+        /* init the MP3 stream */
+    ret = initStream(&lameConfig, &x->x_lamechunk, &x->x_mp3size, &x->x_lame);
+
+        /* check result */
+    if(ret != BE_ERR_SUCCESSFUL)
+    {
+        post("mp3streamout~: error opening encoding stream (%lu)", ret);
+        return;
+    }
+
+#else
+        /* setting lame parameters */
+    lame_set_num_channels( x->lgfp, 2);
+    lame_set_in_samplerate( x->lgfp, sys_getsr() );
+    lame_set_out_samplerate( x->lgfp, x->x_samplerate );
+    lame_set_brate( x->lgfp, x->x_bitrate );
+    lame_set_mode( x->lgfp, x->x_mp3mode );
+    lame_set_quality( x->lgfp, x->x_mp3quality );
+    lame_set_emphasis( x->lgfp, 1 );
+    lame_set_original( x->lgfp, 1 );
+    lame_set_copyright( x->lgfp, 1 ); /* viva free music societies !!! */
+    lame_set_disable_reservoir( x->lgfp, 0 );
+    lame_set_padding_type( x->lgfp, PAD_NO );
+    ret = lame_init_params( x->lgfp );
+    if ( ret<0 ) {
+       post( "mp3streamout~ : error : lame params initialization returned : %d", ret );
+    } else {
+       x->x_lame=1;
+       /* magic formula copied from windows dll for MPEG-I */
+       x->x_lamechunk = 2*1152;
+
+       post( "mp3streamout~ : lame initialization done. (%d)", x->x_lame );
+    }
+    lame_init_bitstream( x->lgfp );
+#endif
+
+
+}
+
+    /* connect to the peer         */
+static void mp3streamout_connect(t_mp3streamout *x, t_symbol *hostname, t_floatarg fportno)
+{
+    struct          sockaddr_in csocket;
+    struct          hostent *hp;
+    int             portno            = fportno;    /* get port from message box */
+
+        /* variables used for communication with the peer */
+    const char      *buf = 0;
+    char            resp[STRBUF_SIZE];
+    unsigned int    len;
+    int    sockfd;
+
+#ifndef UNIX
+    unsigned int    ret;
+#else
+    int    ret;
+#endif
+
+    if (x->x_fd >= 0)
+    {
+        error("mp3streamout~: already connected");
+        return;
+    }
+
+    sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (sockfd < 0)
+    {
+        error("mp3streamout~: internal error while attempting to open socket");
+        return;
+    }
+
+        /* connect socket using hostname provided in command line */
+    csocket.sin_family = AF_INET;
+    hp = gethostbyname(hostname->s_name);
+    if (hp == 0)
+    {
+        post("mp3streamout~: bad host?");
+#ifndef UNIX
+        closesocket(sockfd);
+#else
+        close(sockfd);
+#endif
+        return;
+    }
+    memcpy((char *)&csocket.sin_addr, (char *)hp->h_addr, hp->h_length);
+
+        /* assign client port number */
+    csocket.sin_port = htons((unsigned short)portno);
+
+        /* try to connect.  */
+    post("mp3streamout~: connecting to port %d", portno);
+    if (connect(sockfd, (struct sockaddr *) &csocket, sizeof (csocket)) < 0)
+    {
+        error("mp3streamout~: connection failed!\n");
+#ifndef UNIX
+        closesocket(sockfd);
+#else
+        close(sockfd);
+#endif
+        return;
+    }
+
+    x->x_fd = sockfd;
+    x->x_outpackets = 0;
+    outlet_float( x->x_obj.ob_outlet, 1 );
+    post( "mp3streamout~ : connected to peer" );
+
+    mp3streamout_tilde_lame_init(x);
+
+}
+
+    /* close connection to the peer         */
+static void mp3streamout_disconnect(t_mp3streamout *x)
+{
+
+    int err = -1;
+    if(x->x_lame >= 0)
+    {
+#ifndef UNIX
+            /* deinit the stream */
+        err = deinitStream(x->x_lame, x->x_mp3outbuf, &x->x_mp3size);
+
+            /* check result */
+        if(err != BE_ERR_SUCCESSFUL)
+        {
+            error("exiting mp3 stream failed (%lu)", err);
+        }
+        closeStream(x->x_lame); /* close mp3 encoder stream */
+#else
+            /* ignore remaining bytes */
+        if ( x->x_mp3size = lame_encode_flush( x->lgfp, x->x_mp3outbuf, 0) < 0 ) {
+            post( "mp3streamout~ : warning : remaining encoded bytes" );
+        }
+        lame_close( x->lgfp );
+#endif
+        x->x_lame = -1;
+        post("mp3streamout~: encoder stream closed");
+    }
+
+    if(x->x_fd >= 0)            /* close socket */
+    {
+#ifndef UNIX
+        closesocket(x->x_fd);
+#else
+        close(x->x_fd);
+#endif
+        x->x_fd = -1;
+        outlet_float( x->x_obj.ob_outlet, 0 );
+        post("mp3streamout~: connection closed");
+    }
+}
+
+    /* settings for mp3 encoding */
+static void mp3streamout_mpeg(t_mp3streamout *x, t_floatarg fbitrate,
+                           t_floatarg fmode, t_floatarg fquality)
+{
+    if ( fbitrate != 32 && fbitrate != 40 && fbitrate != 48 && fbitrate != 56 &&
+         fbitrate != 64 && fbitrate != 80 && fbitrate != 96 && fbitrate != 112 &&
+         fbitrate != 128 && fbitrate != 160 && fbitrate != 192 && fbitrate != 224 &&
+         fbitrate != 256 && fbitrate != 320 ) {
+       post( "mp3streamout~ : wrong bitrate." );
+       return;
+    }
+    if ( fmode <0 || fmode>2 ) {
+       post( "mp3streamout~ : wrong mp3 mode." );
+       if ( fmode == 3 )
+       {
+          post( "mp3streamout~ : mone is not supported by streamout~ for now." );
+       }
+       return;
+    }
+    /* there is a bug in lame 3.92 and quality below 5 will not work */
+    /* WAIT FOR A FIX */
+    if ( fquality <5 || fquality>9 ) {
+       post( "mp3streamout~ : wrong quality." );
+       return;
+    }
+    x->x_bitrate = fbitrate;
+    x->x_mp3mode = fmode;
+    x->x_mp3quality = (int)fquality;
+    post("mp3streamout~: setting mp3 stream to %dHz, %dkbit/s, mode %d, quality %d",
+          x->x_samplerate, x->x_bitrate, x->x_mp3mode, x->x_mp3quality);
+    mp3streamout_tilde_lame_init(x);
+}
+
+    /* print settings */
+static void mp3streamout_print(t_mp3streamout *x)
+{
+  const char        * buf = 0;
+
+    post(mp3streamout_version);
+    post("  LAME mp3 settings:\n"
+         "    output sample rate: %d Hz\n"
+         "    bitrate: %d kbit/s", x->x_samplerate, x->x_bitrate);
+    switch(x->x_mp3mode)
+    {
+        case 0 : 
+            buf = "stereo";
+            break;
+        case 1 : 
+            buf = "joint stereo";
+            break;
+        case 2 : 
+            buf = "dual channel";
+            break;
+        case 3 : 
+            buf = "mono";
+            break;
+    }
+    post("    mode: %s\n"
+         "    quality: %d", buf, x->x_mp3quality);
+#ifndef UNIX
+    if(x->x_lamechunk!=0)post("    calculated mp3 chunk size: %d", x->x_lamechunk);
+#else
+    post("    mp3 chunk size: %d", x->x_lamechunk);
+#endif
+    if(x->x_samplerate!=sys_getsr())
+    {
+        post("    resampling from %d to %d Hz!", (int)sys_getsr(), x->x_samplerate);
+    }
+}
+
+    /* clean up */
+static void mp3streamout_free(t_mp3streamout *x)    
+{
+
+    if(x->x_lame >= 0)
+#ifndef UNIX
+        closeStream(x->x_lame);
+#else
+        lame_close( x->lgfp );
+#endif
+    if(x->x_fd >= 0)
+#ifndef UNIX
+        closesocket(x->x_fd);
+#else
+        close(x->x_fd);
+#endif
+    freebytes(x->x_mp3inbuf, MY_MP3_MALLOC_IN_SIZE*sizeof(short));
+    freebytes(x->x_mp3outbuf, MY_MP3_MALLOC_OUT_SIZE);
+    freebytes(x->x_buffer, MY_MP3_MALLOC_IN_SIZE*sizeof(short));
+}
+
+static void *mp3streamout_new(void)
+{
+    t_mp3streamout *x = (t_mp3streamout *)pd_new(mp3streamout_class);
+    inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal"));
+    outlet_new( &x->x_obj, &s_float );
+    x->lgfp = NULL;
+    x->x_fd = -1;
+    x->x_outpackets = 0;
+    x->x_lame = -1;
+    x->x_samplerate = sys_getsr();
+    x->x_bitrate = 128;
+    x->x_mp3mode = 1;
+    x->x_mp3quality = 5;
+    x->x_mp3inbuf = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short));  /* buffer for encoder input */
+    x->x_mp3outbuf = getbytes(MY_MP3_MALLOC_OUT_SIZE);              /* our mp3 stream */
+    x->x_buffer = getbytes(MY_MP3_MALLOC_IN_SIZE*sizeof(short));    /* what we get from pd, converted to PCM */
+    if ((!x->x_buffer)||(!x->x_mp3inbuf)||(!x->x_mp3outbuf))        /* check buffers... */
+    {
+        error("out of memory!");
+    }
+    x->x_bytesbuffered = 0;
+    x->x_inp = 0;
+    x->x_outp = 0;
+    x->x_start = -1;
+    return(x);
+}
+
+void mp3streamout_tilde_setup(void)
+{
+    post(mp3streamout_version);
+    mp3streamout_class = class_new(gensym("mp3streamout~"), (t_newmethod)mp3streamout_new, (t_method)mp3streamout_free,
+        sizeof(t_mp3streamout), 0, 0);
+    CLASS_MAINSIGNALIN(mp3streamout_class, t_mp3streamout, x_f );
+    class_sethelpsymbol(mp3streamout_class, gensym("help-mp3live~.pd"));
+    class_addmethod(mp3streamout_class, (t_method)mp3streamout_dsp, gensym("dsp"), 0);
+    class_addmethod(mp3streamout_class, (t_method)mp3streamout_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0);
+    class_addmethod(mp3streamout_class, (t_method)mp3streamout_disconnect, gensym("disconnect"), 0);
+    class_addmethod(mp3streamout_class, (t_method)mp3streamout_mpeg, gensym("mpeg"), A_FLOAT, A_FLOAT, A_FLOAT, 0);
+    class_addmethod(mp3streamout_class, (t_method)mp3streamout_print, gensym("print"), 0);
+}
+
diff --git a/mp3live~/mpg123.h b/mp3live~/mpg123.h
new file mode 100644
index 0000000..1c530d3
--- /dev/null
+++ b/mp3live~/mpg123.h
@@ -0,0 +1,136 @@
+#ifndef MPG123_H_INCLUDED
+#define MPG123_H_INCLUDED
+
+#include        <stdio.h>
+
+#define STDC_HEADERS 
+
+#ifdef STDC_HEADERS
+# include <string.h>
+#else
+# ifndef HAVE_STRCHR
+#  define strchr index
+#  define strrchr rindex
+# endif
+char *strchr (), *strrchr ();
+# ifndef HAVE_MEMCPY
+#  define memcpy(d, s, n) bcopy ((s), (d), (n))
+#  define memmove(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#include        <signal.h>
+
+
+#if defined(__riscos__) && defined(FPA10)
+#include	"ymath.h"
+#else
+#include	<math.h>
+#endif
+
+#ifndef M_PI
+#define M_PI       3.14159265358979323846
+#endif
+#ifndef M_SQRT2
+#define M_SQRT2    1.41421356237309504880
+#endif
+
+#ifndef FALSE
+#define         FALSE                   0
+#endif
+#ifndef TRUE
+#define         TRUE                    1
+#endif
+
+
+#ifdef REAL_IS_FLOAT
+#  define real float
+#elif defined(REAL_IS_LONG_DOUBLE)
+#  define real long double
+#else
+#  define real double
+#endif
+
+#define         FALSE                   0
+#define         TRUE                    1
+
+#define         SBLIMIT                 32
+#define         SSLIMIT                 18
+
+#define         MPG_MD_STEREO           0
+#define         MPG_MD_JOINT_STEREO     1
+#define         MPG_MD_DUAL_CHANNEL     2
+#define         MPG_MD_MONO             3
+
+#define MAXFRAMESIZE 1792
+
+/* AF: ADDED FOR LAYER1/LAYER2 */
+#define         SCALE_BLOCK             12
+
+
+/* Pre Shift fo 16 to 8 bit converter table */
+#define AUSHIFT (3)
+
+struct frame {
+    int stereo;
+    int jsbound;
+    int single;
+    int lsf;
+    int mpeg25;
+    int header_change;
+    int lay;
+    int error_protection;
+    int bitrate_index;
+    int sampling_frequency;
+    int padding;
+    int extension;
+    int mode;
+    int mode_ext;
+    int copyright;
+    int original;
+    int emphasis;
+    int framesize; /* computed framesize */
+
+	/* AF: ADDED FOR LAYER1/LAYER2 */
+#if defined(USE_LAYER_2) || defined(USE_LAYER_1)
+    int II_sblimit;
+    struct al_table2 *alloc;
+	int down_sample_sblimit;
+	int	down_sample;
+
+#endif
+
+};
+
+struct gr_info_s {
+      int scfsi;
+      unsigned part2_3_length;
+      unsigned big_values;
+      unsigned scalefac_compress;
+      unsigned block_type;
+      unsigned mixed_block_flag;
+      unsigned table_select[3];
+      unsigned subblock_gain[3];
+      unsigned maxband[3];
+      unsigned maxbandl;
+      unsigned maxb;
+      unsigned region1start;
+      unsigned region2start;
+      unsigned preflag;
+      unsigned scalefac_scale;
+      unsigned count1table_select;
+      real *full_gain[3];
+      real *pow2gain;
+};
+
+struct III_sideinfo
+{
+  unsigned main_data_begin;
+  unsigned private_bits;
+  struct {
+    struct gr_info_s gr[2];
+  } ch[2];
+};
+
+
+#endif
diff --git a/mp3live~/mpglib.h b/mp3live~/mpglib.h
new file mode 100644
index 0000000..1f4ef9a
--- /dev/null
+++ b/mp3live~/mpglib.h
@@ -0,0 +1,65 @@
+// #include "lame-analysis.h"
+
+#define NOANALYSIS
+
+#ifndef NOANALYSIS
+extern plotting_data *mpg123_pinfo;
+#endif
+
+struct buf {
+        unsigned char *pnt;
+	long size;
+	long pos;
+        struct buf *next;
+        struct buf *prev;
+};
+
+struct framebuf {
+	struct buf *buf;
+	long pos;
+	struct frame *next;
+	struct frame *prev;
+};
+
+typedef struct mpstr_tag {
+	struct buf *head,*tail;
+        int vbr_header;               /* 1 if valid Xing vbr header detected */
+        int num_frames;               /* set if vbr header present */
+        int enc_delay;                /* set if vbr header present */
+        int enc_padding;              /* set if vbr header present */
+        int header_parsed;
+        int side_parsed;  
+        int data_parsed;  
+        int free_format;             /* 1 = free format frame */
+        int old_free_format;        /* 1 = last frame was free format */
+	int bsize;
+	int framesize;
+	int ssize;
+	int dsize;
+        int fsizeold;
+        int fsizeold_nopadding;
+	struct frame fr;
+        unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */
+	real hybrid_block[2][2][SBLIMIT*SSLIMIT];
+	int hybrid_blc[2];
+	unsigned long header;
+	int bsnum;
+	real synth_buffs[2][2][0x110];
+        int  synth_bo;
+        int  sync_bitstream;
+	
+} MPSTR, *PMPSTR;
+
+
+#if ( defined(_MSC_VER) || defined(__BORLANDC__) )
+	typedef int BOOL; /* windef.h contains the same definition */
+#else
+	#define BOOL int
+#endif
+
+#define MP3_ERR -1
+#define MP3_OK  0
+#define MP3_NEED_MORE 1
+
+
+
diff --git a/mp3live~/test-streaming-mp3.pd b/mp3live~/test-streaming-mp3.pd
new file mode 100644
index 0000000..e9e6b2e
--- /dev/null
+++ b/mp3live~/test-streaming-mp3.pd
@@ -0,0 +1,96 @@
+#N canvas 15 9 986 678 10;
+#X msg 63 58 bang;
+#X obj 63 78 openpanel;
+#X obj 63 100 t s b;
+#X obj 63 137 pack s s;
+#X obj 99 100 float \$0;
+#X text 51 39 Step 1 : Load a sound file;
+#X obj 117 137 makefilename %d-sample;
+#X msg 443 280 \; pd dsp 1;
+#X msg 509 280 \; pd dsp 0;
+#X obj 454 254 loadbang;
+#X obj 62 217 mp3streamout~;
+#X floatatom 63 240 5 0 0;
+#X obj 62 181 readsf~;
+#X msg 62 158 open \$1 \$2;
+#X msg 33 148 1;
+#X msg 265 185 disconnect;
+#X obj 63 117 route float;
+#X msg 569 47 bang;
+#X obj 569 67 openpanel;
+#X obj 569 89 t s b;
+#X obj 569 126 pack s s;
+#X obj 605 89 float \$0;
+#X text 557 28 Step 1 : Load a sound file;
+#X obj 623 126 makefilename %d-sample;
+#X obj 568 206 mp3streamout~;
+#X floatatom 569 229 5 0 0;
+#X obj 568 170 readsf~;
+#X msg 568 147 open \$1 \$2;
+#X msg 539 137 1;
+#X msg 784 177 disconnect;
+#X obj 569 106 route float;
+#X obj 364 462 dac~;
+#X obj 361 438 *~;
+#X floatatom 416 465 5 0 0;
+#X symbolatom 459 437 15 0 0;
+#X obj 407 440 / 100;
+#X obj 122 470 dac~;
+#X obj 119 446 *~;
+#X floatatom 174 473 5 0 0;
+#X symbolatom 217 445 10 0 0;
+#X obj 165 448 / 100;
+#X obj 96 419 mp3streamin~ 5001 1;
+#X obj 345 410 mp3streamin~ 5000 1;
+#X msg 777 149 connect yves 5001;
+#X msg 246 228 mpeg 32 2 5;
+#X msg 246 228 mpeg 32 2 5;
+#X msg 246 264 mpeg 224 2 5;
+#X msg 258 157 connect localhost 5000;
+#X msg 263 125 connect dregs 5000;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 2 1 4 0;
+#X connect 3 0 13 0;
+#X connect 4 0 16 0;
+#X connect 6 0 3 1;
+#X connect 9 0 7 0;
+#X connect 10 0 11 0;
+#X connect 12 0 10 0;
+#X connect 12 0 10 1;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 10 0;
+#X connect 16 0 6 0;
+#X connect 17 0 18 0;
+#X connect 18 0 19 0;
+#X connect 19 0 20 0;
+#X connect 19 1 21 0;
+#X connect 20 0 27 0;
+#X connect 21 0 30 0;
+#X connect 23 0 20 1;
+#X connect 24 0 25 0;
+#X connect 26 0 24 0;
+#X connect 26 0 24 1;
+#X connect 27 0 26 0;
+#X connect 28 0 26 0;
+#X connect 29 0 24 0;
+#X connect 30 0 23 0;
+#X connect 32 0 31 0;
+#X connect 32 0 31 1;
+#X connect 33 0 35 0;
+#X connect 35 0 32 1;
+#X connect 37 0 36 0;
+#X connect 37 0 36 1;
+#X connect 38 0 40 0;
+#X connect 40 0 37 1;
+#X connect 41 0 37 0;
+#X connect 41 2 39 0;
+#X connect 42 0 32 0;
+#X connect 42 2 34 0;
+#X connect 43 0 24 0;
+#X connect 44 0 10 0;
+#X connect 46 0 10 0;
+#X connect 47 0 10 0;
+#X connect 48 0 10 0;
-- 
cgit v1.2.1