From 506b8e7dedb80d79bf015e47d92e8b8dd8284584 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 16 Aug 2003 17:08:55 +0000 Subject: added files straight from Yves' sources svn path=/trunk/externals/unauthorized/; revision=864 --- mp3cast~/CHANGES.LOG | 6 + mp3cast~/INSTALL | 15 + mp3cast~/Makefile | 82 +++++ mp3cast~/Makefile.linux | 82 +++++ mp3cast~/README | 108 ++++++ mp3cast~/help-mp3cast~.pd | 50 +++ mp3cast~/interface.h | 32 ++ mp3cast~/mp3cast~.c | 916 ++++++++++++++++++++++++++++++++++++++++++++++ mp3cast~/mpg123.h | 136 +++++++ mp3cast~/mpglib.h | 65 ++++ 10 files changed, 1492 insertions(+) create mode 100644 mp3cast~/CHANGES.LOG create mode 100644 mp3cast~/INSTALL create mode 100644 mp3cast~/Makefile create mode 100644 mp3cast~/Makefile.linux create mode 100644 mp3cast~/README create mode 100644 mp3cast~/help-mp3cast~.pd create mode 100644 mp3cast~/interface.h create mode 100644 mp3cast~/mp3cast~.c create mode 100644 mp3cast~/mpg123.h create mode 100644 mp3cast~/mpglib.h (limited to 'mp3cast~') diff --git a/mp3cast~/CHANGES.LOG b/mp3cast~/CHANGES.LOG new file mode 100644 index 0000000..7418ad7 --- /dev/null +++ b/mp3cast~/CHANGES.LOG @@ -0,0 +1,6 @@ +0.3 + renamed it to mp3cast +0.2 + fixed multi-encoding problem +0.1 + first implementation diff --git a/mp3cast~/INSTALL b/mp3cast~/INSTALL new file mode 100644 index 0000000..769e78e --- /dev/null +++ b/mp3cast~/INSTALL @@ -0,0 +1,15 @@ +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/mp3cast~ + +make -f Makefile.linux + +make -f Makefile.linux install + +you're set !! diff --git a/mp3cast~/Makefile b/mp3cast~/Makefile new file mode 100644 index 0000000..799788e --- /dev/null +++ b/mp3cast~/Makefile @@ -0,0 +1,82 @@ +NAME=mp3cast~ +CSYM=mp3cast_tilde + +current: pd_linux + +# ----------------------- NT ----------------------- + +pd_nt: $(NAME).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 + +.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 + +.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 + +.SUFFIXES: .pd_linux + +LINUXCFLAGS = -DPD -DUNIX -DICECAST -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) -DHAVE_STRCHR -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 $*/$*.pd_linux .. + +# ---------------------------------------------------------- + +install: + cp help-*.pd ../../doc/5.reference + +clean: + rm -f *.o *.pd_* so_locations diff --git a/mp3cast~/Makefile.linux b/mp3cast~/Makefile.linux new file mode 100644 index 0000000..b2f9cfa --- /dev/null +++ b/mp3cast~/Makefile.linux @@ -0,0 +1,82 @@ +NAME=mp3cast~ +CSYM=mp3cast_tilde + +current: pd_linux + +# ----------------------- NT ----------------------- + +pd_nt: $(NAME).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 + +.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 + +.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 + +.SUFFIXES: .pd_linux + +LINUXCFLAGS = -DPD -DUNIX -DICECAST -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 $*/$*.pd_linux .. + +# ---------------------------------------------------------- + +install: + cp test-*.pd ../../doc/5.reference + +clean: + rm -f *.o *.pd_* so_locations diff --git a/mp3cast~/README b/mp3cast~/README new file mode 100644 index 0000000..99c2bbc --- /dev/null +++ b/mp3cast~/README @@ -0,0 +1,108 @@ +Version 0.01 +copyright (c) 2001 by Olaf Matthes +ported to Linux by Yves Degoyon + +mp3cast~.dll is a MPEG I Layer III (mp3) streaming external for pd (by Miller +Puckette) that connects to a SHOUTcast or IceCast server. + +To install mp3cast~, 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. + +***************************************************************************** + +mp3cast~ 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. + +***************************************************************************** + + using mp3cast~ external for Pure Data + +Open the test-mp3cast~.pd to understand how it works. +In this patch, you must send the messages to mp3cast~ +in the following order : + +1/ password ***** +2/ icecast | mp3cast +3/ connect host port +4/ pd dsp 1 + +Parameters sent to mp3cast~ object : + + Sampling Rate (Hz): +Possible values are 48000, 44100 and 32000. If Pd runs at a different sampling +rate, LAME will resample the signal. Default value for mp3 sampling rate is Pd's +sampling rate. + + Bitrate (kbit/s): +Possible values are 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 +and 320. Default is 224. + + Mode: +Possible values are 0 (stereo), 1 (joint stereo, the default), 2 (dual channel) +and 3 (mono). + + Password: +The default is 'pd', can be changed with a message "passwd yourpassword". + + Server: +Use message "connect name_of_your_server.com port" to connect (same as with +Pd's netsend). 'port' is the number specified in the server's config file. +Attention (for SHOUTcast users): The actual port number used is one higher! +Standard would be 8000 resulting in a socket at port 8001!!! Bare this in mind +when configuring proxys or using mp3cast~ in connection with netsend / +netreceive. For IceCast, the port number used is the same as specified. + + Outlet: +The outlet outputs an int, 1 if connected to SHOUTcast server, 0 if not. This could +be used to build an automatic reconnect mechanism. + + Other things: +mp3cast~ prints the current status (connection, login, LAME status) to the pd +window. To see the current settings, send it a message "print" and mp3 settings +will be displayed. +Note that changing any mp3 settings will require to disconnect and reconnect again! +This has to be done manually. + + Known problems: +If you turn off audio processing when you are connected with the server, no data will +be sent to it. This will make the server disconnect after a certain time ('no data' +error in server log). mp3cast~ does not recongnise this and attempts to keep on +streaming. To avoid this set 'AutoDumpSourceTime' in the servers config file to a +fairly high value preventing the server from closing the socket to fast. + +ALLOWED QUALITY FACTOR : + + -q = 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 SAMPLERATE/BITRATES + +MPEG-1 layer III sample frequencies (kHz): 32 48 44.1 +bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320 + +MPEG-2 layer III sample frequencies (kHz): 16 24 22.05 +bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160 + +MPEG-2.5 layer III sample frequencies (kHz): 8 12 11.025 +bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160 + diff --git a/mp3cast~/help-mp3cast~.pd b/mp3cast~/help-mp3cast~.pd new file mode 100644 index 0000000..c7d8e72 --- /dev/null +++ b/mp3cast~/help-mp3cast~.pd @@ -0,0 +1,50 @@ +#N canvas 52 75 741 425 10; +#X floatatom 53 24 0 40 16000; +#X msg 30 378 \; pd dsp 1; +#X obj 61 242 mp3cast~; +#X floatatom 61 280 0 0 0; +#X msg 181 88 disconnect; +#X msg 151 44 connect localhost 8000; +#X text 266 63 <-- your password for the server; +#X text 317 75 (default passwd is "pd"); +#X text 257 87 <-- close connection; +#X text 411 21 <-- host and port; +#X text 292 215 <-- settings for mp3 stream; +#X text 315 245 bitrate: bitrate of stream \, def. 224kbit/s; +#X text 352 269 1 = joint stereo (default); +#X text 312 307 quality: 1 = high \, 9 = low; +#X text 313 227 (samplerate \, bitrate \, mode \, quality); +#X text 316 257 mode: 0 = stereo; +#X text 352 281 2 = dual channel; +#X text 352 294 3 = mono; +#X msg 13 145 print; +#X msg 96 378 \; pd dsp 0; +#X msg 203 141 icecast; +#X text 259 116 <-- choose type of server; +#X obj 53 51 osc~ 440; +#X msg 163 66 passwd letmein; +#X msg 154 239 mpeg 8000 8 3 5; +#X msg 155 215 mpeg 44100 128 1 4; +#X msg 209 170 mountpoint pd; +#X obj 29 349 loadbang; +#X text 293 374 Author : Yves Degoyon ( ydegoyon@free.fr ); +#X msg 190 118 shoutcast; +#X msg 116 23 connect college-invisible.dyndns.org 8000; +#X msg 212 194 name mystream; +#X text 322 195 name of the stream; +#X connect 0 0 22 0; +#X connect 2 0 3 0; +#X connect 4 0 2 0; +#X connect 5 0 2 0; +#X connect 18 0 2 0; +#X connect 20 0 2 0; +#X connect 22 0 2 0; +#X connect 22 0 2 1; +#X connect 23 0 2 0; +#X connect 24 0 2 0; +#X connect 25 0 2 0; +#X connect 26 0 2 0; +#X connect 27 0 1 0; +#X connect 29 0 2 0; +#X connect 30 0 2 0; +#X connect 31 0 2 0; diff --git a/mp3cast~/interface.h b/mp3cast~/interface.h new file mode 100644 index 0000000..de3136a --- /dev/null +++ b/mp3cast~/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/mp3cast~/mp3cast~.c b/mp3cast~/mp3cast~.c new file mode 100644 index 0000000..5c881c3 --- /dev/null +++ b/mp3cast~/mp3cast~.c @@ -0,0 +1,916 @@ +/* ------------------------ mp3cast~ ---------------------------------------- */ +/* */ +/* Tilde object to send mp3-stream to shoutcast/icecast server. */ +/* Written by Olaf Matthes (olaf.matthes@gmx.de). */ +/* Get source at http://www.akustische-kunst.de/puredata/ */ +/* */ +/* 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. */ +/* */ +/* ---------------------------------------------------------------------------- */ + + + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include "m_pd.h" /* standard pd stuff */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef UNIX +#include +#include +#include +#include +#include +#include +#include /* lame encoder stuff */ +#include "mpg123.h" +#define SOCKET_ERROR -1 +#else +#include +#include +#include +#include +#include "lame_enc.h" /* lame encoder stuff */ +#endif + + +#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 *mp3cast_version = "mp3cast~: mp3 streamer version 0.3, written by Yves Degoyon"; + +#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 *mp3cast_class; + +typedef struct _mp3cast +{ + 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 */ + + /* SHOUTcast server stuff */ + int x_fd; /* info about connection status */ + char* x_passwd; /* password for server */ + int x_icecast; /* tells if we use a IceCast server or SHOUTcast */ + /* special IceCast server stuff */ + char* x_mountpoint; + char* x_name; + + t_float x_f; /* float needed for signal input */ + +#ifdef UNIX + lame_global_flags *lgfp; /* lame encoder configuration */ +#endif + +} t_mp3cast; + + + /* encode PCM data to mp3 stream */ +static void mp3cast_encode(t_mp3cast *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("mp3cast~: initialising 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("mp3cast~: 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); + // post( "mp3cast~ : encoding returned %d frames", x->x_mp3size ); +#endif + + /* check result */ +#ifndef UNIX + if(err != BE_ERR_SUCCESSFUL) + { + closeStream(x->x_lame); + error("mp3cast~: lameEncodeChunk() failed (%lu)", err); +#else + if(x->x_mp3size<0) + { + lame_close( x->lgfp ); + error("mp3cast~: lame_encode_buffer_interleaved failed (%d)", x->x_mp3size); +#endif + x->x_lame = -1; + } +} + + + /* stream mp3 to SHOUTcast server */ +static void mp3cast_stream(t_mp3cast *x) +{ + int err = -1, i; /* error return code */ + struct frame hframe; + + err = send(x->x_fd, x->x_mp3outbuf, x->x_mp3size, 0); + if(err < 0) + { + error("mp3cast~: could not send encoded data to server (%d)", err); +#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); + } + if((err > 0)&&(err != x->x_mp3size))error("mp3cast~: %d bytes skipped", x->x_mp3size - err); +} + + + /* buffer data as channel interleaved PCM */ +static t_int *mp3cast_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_mp3cast *x = (t_mp3cast *)(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 server */ + if(x->x_bytesbuffered > x->x_lamechunk) + { + mp3cast_encode(x); /* encode to mp3 */ + mp3cast_stream(x); /* stream mp3 to server */ + x->x_bytesbuffered -= x->x_lamechunk; + } + } + else + { + x->x_start = -1; + } + return (w+5); +} + +static void mp3cast_dsp(t_mp3cast *x, t_signal **sp) +{ + dsp_add(mp3cast_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); +} + + /* initialize the lame library */ +static void mp3cast_tilde_lame_init(t_mp3cast *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("mp3cast~: error loading lame_enc.dll"); + closesocket(x->x_fd); + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + post("mp3cast~: 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("mp3cast~: unable to get LAME interfaces"); + closesocket(x->x_fd); + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + post("mp3cast~: connection closed"); + return; + } + + /* get LAME version number */ + dllVersion(&lameVersion); + + post( "mp3cast~: 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( "mp3cast~ : 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("mp3cast~: 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( "mp3cast~ : 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( "mp3cast~ : lame initialization done. (%d)", x->x_lame ); + } + lame_init_bitstream( x->lgfp ); +#endif + + +} + + /* connect to SHOUTcast server */ +static void mp3cast_connect(t_mp3cast *x, t_symbol *hostname, t_floatarg fportno) +{ + struct sockaddr_in server; + struct hostent *hp; + int portno = fportno; /* get port from message box */ + + /* information about this broadcast to be send to the server */ + const char *name = x->x_name; /* name of broadcast */ + const char *url = "http://guess.where.i.am"; /* url of broadcast */ + const char *genre = "abstract break"; /* genre of broadcast */ + const char *aim = "N/A"; /* aim of broadcast */ + const char *irc = "#mp3cast"; /* ??? what's this ??? */ + const char *icq = ""; /* icq id of broadcaster */ + const char *mountpoint = x->x_mountpoint; /* mountpoint for IceCast server */ + int isPublic = 0; /* don't publish broadcast on www.shoutcast.com */ + + /* variables used for communication with server */ + const char * buf = 0; + char resp[STRBUF_SIZE]; + unsigned int len; + fd_set fdset; + struct timeval tv; + int sockfd; + +#ifndef UNIX + unsigned int ret; +#else + int ret; +#endif + + if(x->x_icecast == 0)portno++; /* use SHOUTcast, portno is one higher */ + + if (x->x_fd >= 0) + { + error("mp3cast~: already connected"); + return; + } + + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd < 0) + { + error("mp3cast~: internal error while attempting to open socket"); + return; + } + + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + hp = gethostbyname(hostname->s_name); + if (hp == 0) + { + post("mp3cast~: bad host?"); +#ifndef UNIX + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + server.sin_port = htons((unsigned short)portno); + + /* try to connect. */ + post("mp3cast~: connecting to port %d", portno); + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + error("mp3cast~: connection failed!\n"); +#ifndef UNIX + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + + /* sheck if we can read/write from/to the socket */ + FD_ZERO( &fdset); + FD_SET( sockfd, &fdset); + tv.tv_sec = 0; /* seconds */ + tv.tv_usec = 500; /* microseconds */ + + ret = select(sockfd + 1, &fdset, NULL, NULL, &tv); + if(ret < 0) + { + error("mp3cast~: can not read from socket"); +#ifndef UNIX + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + ret = select(sockfd + 1, NULL, &fdset, NULL, &tv); + if(ret < 0) + { + error("mp3cast~: can not write to socket"); +#ifndef UNIX + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + + if(x->x_icecast == 0) /* SHOUTCAST */ + { + /* now try to log in at SHOUTcast server */ + post("mp3cast~: logging in to SHOUTcast server..."); + + /* first line is the passwd */ + buf = x->x_passwd; + send(sockfd, buf, strlen(buf), 0); + buf = "\n"; + send(sockfd, buf, strlen(buf), 0); + + /* header for SHOUTcast server */ + buf = "icy-name:"; /* name of broadcast */ + send(sockfd, buf, strlen(buf), 0); + buf = name; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-url:"; /* URL of broadcast */ + send(sockfd, buf, strlen(buf), 0); + buf = url; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-genre:"; /* genre of broadcast */ + send(sockfd, buf, strlen(buf), 0); + buf = genre; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-irc:"; + send(sockfd, buf, strlen(buf), 0); + buf = irc; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-aim:"; + send(sockfd, buf, strlen(buf), 0); + buf = aim; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-icq:"; + send(sockfd, buf, strlen(buf), 0); + buf = icq; + send(sockfd, buf, strlen(buf), 0); + buf = "\nicy-br:"; + send(sockfd, buf, strlen(buf), 0); + if(sprintf(resp, "%d", x->x_bitrate) == -1) /* convert int to a string */ + { + error("mp3cast~: wrong bitrate"); + } + send(sockfd, resp, strlen(resp), 0); + buf = "\nicy-pub:"; + send(sockfd, buf, strlen(buf), 0); + if(isPublic==0) /* set the public flag for broadcast */ + { + buf = "no"; + } + else + { + buf ="yes"; + } + send(sockfd, buf, strlen(buf), 0); + buf = "\n\n"; + send(sockfd, buf, strlen(buf), 0); + } + else /* IceCast */ + { + /* now try to log in at IceCast server */ + post("mp3cast~: logging in to IceCast server..."); + + /* send the request, a string like: + * "SOURCE /\n" */ + buf = "SOURCE "; + send(sockfd, buf, strlen(buf), 0); + buf = x->x_passwd; + send(sockfd, buf, strlen(buf), 0); + buf = " /"; + send(sockfd, buf, strlen(buf), 0); + buf = mountpoint; + send(sockfd, buf, strlen(buf), 0); + + /* send the x-audiocast headers */ + buf = "\nx-audiocast-bitrate: "; + send(sockfd, buf, strlen(buf), 0); + if(sprintf(resp, "%d", x->x_bitrate) == -1) /* convert int to a string */ + { + error("mp3cast~: wrong bitrate"); + } + send(sockfd, resp, strlen(resp), 0); + + buf = "\nx-audiocast-public: "; + send(sockfd, buf, strlen(buf), 0); + if(isPublic==0) /* set the public flag for broadcast */ + { + buf = "no"; + } + else + { + buf ="yes"; + } + send(sockfd, buf, strlen(buf), 0); + + buf = "\nx-audiocast-name: "; + send(sockfd, buf, strlen(buf), 0); + buf = name; + send(sockfd, buf, strlen(buf), 0); + + buf = "\nx-audiocast-url: "; + send(sockfd, buf, strlen(buf), 0); + buf = url; + send(sockfd, buf, strlen(buf), 0); + + buf = "\nx-audiocast-genre: "; + send(sockfd, buf, strlen(buf), 0); + buf = genre; + send(sockfd, buf, strlen(buf), 0); + + buf = "\n\n"; + send(sockfd, buf, strlen(buf), 0); + /* end login for IceCast */ + } + + /* read the anticipated response: "OK" */ + len = recv(sockfd, resp, STRBUF_SIZE, 0); + if ( len < 2 || resp[0] != 'O' || resp[1] != 'K' ) + { + post("mp3cast~: login failed!"); +#ifndef UNIX + closesocket(sockfd); +#else + close(sockfd); +#endif + return; + } + + /* suck anything that the other side has to say */ + // while (len = recv(sockfd, resp, STRBUF_SIZE,0)) + // { + ; /* do nothing, just wait ! */ + // } + + x->x_fd = sockfd; + outlet_float(x->x_obj.ob_outlet, 1); + post("mp3cast~: logged in to %s", hp->h_name); + + mp3cast_tilde_lame_init(x); + +} + + /* close connection to SHOUTcast server */ +static void mp3cast_disconnect(t_mp3cast *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( "mp3cast~ : warning : remaining encoded bytes" ); + } + lame_close( x->lgfp ); +#endif + x->x_lame = -1; + post("mp3cast~: 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("mp3cast~: connection closed"); + } +} + + /* set password for SHOUTcast server */ +static void mp3cast_password(t_mp3cast *x, t_symbol *password) +{ + post("mp3cast~ : setting password to %s", password->s_name ); + x->x_passwd = password->s_name; +} + + /* settings for mp3 encoding */ +static void mp3cast_mpeg(t_mp3cast *x, t_floatarg fsamplerate, t_floatarg fbitrate, + t_floatarg fmode, t_floatarg fquality) +{ + x->x_samplerate = fsamplerate; + if(fbitrate > MAXDATARATE) + { + fbitrate = MAXDATARATE; + } + x->x_bitrate = fbitrate; + x->x_mp3mode = fmode; + x->x_mp3quality = fquality; + post("mp3cast~: setting mp3 stream to %dHz, %dkbit/s, mode %d, quality %d", + x->x_samplerate, x->x_bitrate, x->x_mp3mode, x->x_mp3quality); + if(x->x_fd>=0)post("mp3cast~ : reconnect to make changes take effect! "); +} + + /* print settings */ +static void mp3cast_print(t_mp3cast *x) +{ + const char * buf = 0; + post(mp3cast_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); + } + if(x->x_icecast == 0) + { + post(" server type is SHOUTcast"); + } + else + { + post(" server type is IceCast"); + } +} + + /* we use iceCast server */ +static void mp3cast_icecast(t_mp3cast *x) +{ + x->x_icecast = 1; + post("mp3cast~: set server type to IceCast"); +} + + /* we use SHOUTcast server (default) */ +static void mp3cast_shoutcast(t_mp3cast *x) +{ + x->x_icecast = 0; + post("mp3cast~: set server type to SHOUTcast"); +} + + /* set mountpoint for IceCast server */ +static void mp3cast_mountpoint(t_mp3cast *x, t_symbol *mount) +{ + x->x_mountpoint = mount->s_name; + post("mp3cast~: mountpoint set to %s", x->x_mountpoint); +} + + /* set namle for IceCast server */ +static void mp3cast_name(t_mp3cast *x, t_symbol *name) +{ + x->x_name = name->s_name; + post("mp3cast~: name set to %s", x->x_name); +} + + /* clean up */ +static void mp3cast_free(t_mp3cast *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 *mp3cast_new(void) +{ + t_mp3cast *x = (t_mp3cast *)pd_new(mp3cast_class); + inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal")); + outlet_new(&x->x_obj, gensym("float")); + x->x_fd = -1; + x->x_lame = -1; + x->x_passwd = "pd"; + x->x_samplerate = sys_getsr(); + x->x_bitrate = 224; + 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*sizeof(char)); /* 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->lgfp = NULL; + x->x_start = -1; + x->x_icecast = 0; + x->x_mountpoint = "puredata"; + x->x_name = "puredata"; + return(x); +} + +void mp3cast_tilde_setup(void) +{ + post(mp3cast_version); + mp3cast_class = class_new(gensym("mp3cast~"), (t_newmethod)mp3cast_new, (t_method)mp3cast_free, + sizeof(t_mp3cast), 0, 0); + CLASS_MAINSIGNALIN(mp3cast_class, t_mp3cast, x_f ); + class_sethelpsymbol(mp3cast_class, gensym("help-mp3cast~.pd")); + class_addmethod(mp3cast_class, (t_method)mp3cast_dsp, gensym("dsp"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_connect, gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_disconnect, gensym("disconnect"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_password, gensym("passwd"), A_SYMBOL, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_mpeg, gensym("mpeg"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_print, gensym("print"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_icecast, gensym("icecast"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_shoutcast, gensym("shoutcast"), 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_mountpoint, gensym("mountpoint"), A_SYMBOL, 0); + class_addmethod(mp3cast_class, (t_method)mp3cast_name, gensym("name"), A_SYMBOL, 0); +} + diff --git a/mp3cast~/mpg123.h b/mp3cast~/mpg123.h new file mode 100644 index 0000000..1c530d3 --- /dev/null +++ b/mp3cast~/mpg123.h @@ -0,0 +1,136 @@ +#ifndef MPG123_H_INCLUDED +#define MPG123_H_INCLUDED + +#include + +#define STDC_HEADERS + +#ifdef STDC_HEADERS +# include +#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 + + +#if defined(__riscos__) && defined(FPA10) +#include "ymath.h" +#else +#include +#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/mp3cast~/mpglib.h b/mp3cast~/mpglib.h new file mode 100644 index 0000000..1f4ef9a --- /dev/null +++ b/mp3cast~/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 + + + -- cgit v1.2.1