diff options
Diffstat (limited to 'mp3live~')
-rw-r--r-- | mp3live~/INSTALL | 21 | ||||
-rw-r--r-- | mp3live~/interface.h | 32 | ||||
-rw-r--r-- | mp3live~/mp3fileout~.c | 558 | ||||
-rw-r--r-- | mp3live~/mp3live~-help.pd | 118 | ||||
-rw-r--r-- | mp3live~/mp3streamin~.c | 671 | ||||
-rw-r--r-- | mp3live~/mp3streamout~.c | 617 | ||||
-rw-r--r-- | mp3live~/mpglib.h | 65 | ||||
-rw-r--r-- | mp3live~/test-streaming-mp3.pd | 96 |
8 files changed, 0 insertions, 2178 deletions
diff --git a/mp3live~/INSTALL b/mp3live~/INSTALL deleted file mode 100644 index 63db4c7..0000000 --- a/mp3live~/INSTALL +++ /dev/null @@ -1,21 +0,0 @@ -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~/interface.h b/mp3live~/interface.h deleted file mode 100644 index de3136a..0000000 --- a/mp3live~/interface.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** 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 deleted file mode 100644 index bd2d431..0000000 --- a/mp3live~/mp3fileout~.c +++ /dev/null @@ -1,558 +0,0 @@ -/* ------------------------ 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_pd.h> -#include <m_imp.h> -#include <g_canvas.h> - -#include <sys/types.h> -#include <string.h> -#ifdef _WIN32 -#include <winsock.h> -#include <io.h> -#include <fcntl.h> -#else -#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 -#endif /* _WIN32 */ - -#if defined(__APPLE__) || defined(_WIN32) -#define MSG_NOSIGNAL 0 -#endif - - -#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 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); -#else - sys_rmpollfn(fd); -#endif -} - -/* ------------------------ 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); -} diff --git a/mp3live~/mp3live~-help.pd b/mp3live~/mp3live~-help.pd deleted file mode 100644 index ac68464..0000000 --- a/mp3live~/mp3live~-help.pd +++ /dev/null @@ -1,118 +0,0 @@ -#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~/mp3streamin~.c b/mp3live~/mp3streamin~.c deleted file mode 100644 index b01a576..0000000 --- a/mp3live~/mp3streamin~.c +++ /dev/null @@ -1,671 +0,0 @@ -/* ------------------------ 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_pd.h> -#include <m_imp.h> -#include <g_canvas.h> - -#if PD_MINOR_VERSION >=37 -#include "s_stuff.h" -#endif - -#include <sys/types.h> -#include <string.h> -#ifdef _WIN32 -#include <io.h> -#include <winsock.h> -#else -#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 -#endif /* _WIN32 */ - -#if defined(__APPLE__) || defined(_WIN32) -#define MSG_NOSIGNAL 0 -#define SOL_TCP IPPROTO_TCP -#endif - -#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 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); -} diff --git a/mp3live~/mp3streamout~.c b/mp3live~/mp3streamout~.c deleted file mode 100644 index 33555ce..0000000 --- a/mp3live~/mp3streamout~.c +++ /dev/null @@ -1,617 +0,0 @@ -/* ------------------------ 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 -- */ -/* ---------------------------------------------------------------------------- */ - -#include <sys/types.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/stat.h> -#ifndef __APPLE__ -#include <malloc.h> -#endif -#include <ctype.h> -#ifdef _WIN32 -#include <io.h> -#include <windows.h> -#include <winsock.h> -#include <windef.h> -#else -#include <unistd.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <time.h> -#include <sys/time.h> -#define SOCKET_ERROR -1 -#endif - -#if defined(__APPLE__) || defined(_WIN32) -#define MSG_NOSIGNAL 0 -#endif - -#include <lame/lame.h> /* lame encoder stuff */ - -#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"; - -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 */ - - lame_global_flags* lgfp; -} 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 */ - - 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 ); - - /* check result */ - if(x->x_mp3size<0) - { - lame_close( x->lgfp ); - error("mp3streamout~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size); - 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); - lame_close( x->lgfp ); - 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) -{ - int ret; - x->lgfp = lame_init(); /* set default parameters for now */ - -#ifndef UNIX - /* load lame_enc.dll library */ - HINSTANCE dll; - 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; - } -#endif - { - const char *lameVersion = get_lame_version(); - post( "mp3streamout~ : using lame version : %s", lameVersion ); - } - - /* 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 ); -} - - /* 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) - { - /* 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 ); - 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) - lame_close( x->lgfp ); - - 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_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~/mpglib.h b/mp3live~/mpglib.h deleted file mode 100644 index 1f4ef9a..0000000 --- a/mp3live~/mpglib.h +++ /dev/null @@ -1,65 +0,0 @@ -// #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 deleted file mode 100644 index e9e6b2e..0000000 --- a/mp3live~/test-streaming-mp3.pd +++ /dev/null @@ -1,96 +0,0 @@ -#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; |