diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2003-04-23 10:36:25 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2003-04-23 10:36:25 +0000 |
commit | 6d4b0233efc1a8b1860bf275a2d42b282021a57a (patch) | |
tree | cc68998343273bb2b775ce14756e1e19a097d540 /oggwrite~ | |
parent | 2979b062ddcbdc9f2c78fe410a322b470e4a29db (diff) |
check-in of packaged version 0.23 for Olaf....
svn path=/trunk/externals/pdogg/; revision=590
Diffstat (limited to 'oggwrite~')
-rw-r--r-- | oggwrite~/codec.h | 466 | ||||
-rw-r--r-- | oggwrite~/help-oggwrite~.pd | 118 | ||||
-rw-r--r-- | oggwrite~/oggwrite~.c | 1502 | ||||
-rw-r--r-- | oggwrite~/readme | 218 | ||||
-rw-r--r-- | oggwrite~/vorbisenc.h | 186 |
5 files changed, 1245 insertions, 1245 deletions
diff --git a/oggwrite~/codec.h b/oggwrite~/codec.h index 9365ea3..d986a9b 100644 --- a/oggwrite~/codec.h +++ b/oggwrite~/codec.h @@ -1,233 +1,233 @@ -/********************************************************************
- * *
- * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
- * by the XIPHOPHORUS Company http://www.xiph.org/ *
-
- ********************************************************************
-
- function: libvorbis codec headers
- last mod: $Id: codec.h,v 1.1 2002-11-26 10:51:49 ggeiger Exp $
-
- ********************************************************************/
-
-#ifndef _vorbis_codec_h_
-#define _vorbis_codec_h_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-#include <ogg/ogg.h>
-
-typedef struct vorbis_info{
- int version;
- int channels;
- long rate;
-
- /* The below bitrate declarations are *hints*.
- Combinations of the three values carry the following implications:
-
- all three set to the same value:
- implies a fixed rate bitstream
- only nominal set:
- implies a VBR stream that averages the nominal bitrate. No hard
- upper/lower limit
- upper and or lower set:
- implies a VBR bitstream that obeys the bitrate limits. nominal
- may also be set to give a nominal rate.
- none set:
- the coder does not care to speculate.
- */
-
- long bitrate_upper;
- long bitrate_nominal;
- long bitrate_lower;
- long bitrate_window;
-
- void *codec_setup;
-} vorbis_info;
-
-/* vorbis_dsp_state buffers the current vorbis audio
- analysis/synthesis state. The DSP state belongs to a specific
- logical bitstream ****************************************************/
-typedef struct vorbis_dsp_state{
- int analysisp;
- vorbis_info *vi;
-
- float **pcm;
- float **pcmret;
- int pcm_storage;
- int pcm_current;
- int pcm_returned;
-
- int preextrapolate;
- int eofflag;
-
- long lW;
- long W;
- long nW;
- long centerW;
-
- ogg_int64_t granulepos;
- ogg_int64_t sequence;
-
- ogg_int64_t glue_bits;
- ogg_int64_t time_bits;
- ogg_int64_t floor_bits;
- ogg_int64_t res_bits;
-
- void *backend_state;
-} vorbis_dsp_state;
-
-typedef struct vorbis_block{
- /* necessary stream state for linking to the framing abstraction */
- float **pcm; /* this is a pointer into local storage */
- oggpack_buffer opb;
-
- long lW;
- long W;
- long nW;
- int pcmend;
- int mode;
-
- int eofflag;
- ogg_int64_t granulepos;
- ogg_int64_t sequence;
- vorbis_dsp_state *vd; /* For read-only access of configuration */
-
- /* local storage to avoid remallocing; it's up to the mapping to
- structure it */
- void *localstore;
- long localtop;
- long localalloc;
- long totaluse;
- struct alloc_chain *reap;
-
- /* bitmetrics for the frame */
- long glue_bits;
- long time_bits;
- long floor_bits;
- long res_bits;
-
- void *internal;
-
-} vorbis_block;
-
-/* vorbis_block is a single block of data to be processed as part of
-the analysis/synthesis stream; it belongs to a specific logical
-bitstream, but is independant from other vorbis_blocks belonging to
-that logical bitstream. *************************************************/
-
-struct alloc_chain{
- void *ptr;
- struct alloc_chain *next;
-};
-
-/* vorbis_info contains all the setup information specific to the
- specific compression/decompression mode in progress (eg,
- psychoacoustic settings, channel setup, options, codebook
- etc). vorbis_info and substructures are in backends.h.
-*********************************************************************/
-
-/* the comments are not part of vorbis_info so that vorbis_info can be
- static storage */
-typedef struct vorbis_comment{
- /* unlimited user comment fields. libvorbis writes 'libvorbis'
- whatever vendor is set to in encode */
- char **user_comments;
- int *comment_lengths;
- int comments;
- char *vendor;
-
-} vorbis_comment;
-
-
-/* libvorbis encodes in two abstraction layers; first we perform DSP
- and produce a packet (see docs/analysis.txt). The packet is then
- coded into a framed OggSquish bitstream by the second layer (see
- docs/framing.txt). Decode is the reverse process; we sync/frame
- the bitstream and extract individual packets, then decode the
- packet back into PCM audio.
-
- The extra framing/packetizing is used in streaming formats, such as
- files. Over the net (such as with UDP), the framing and
- packetization aren't necessary as they're provided by the transport
- and the streaming layer is not used */
-
-/* Vorbis PRIMITIVES: general ***************************************/
-
-extern void vorbis_info_init(vorbis_info *vi);
-extern void vorbis_info_clear(vorbis_info *vi);
-extern int vorbis_info_blocksize(vorbis_info *vi,int zo);
-extern void vorbis_comment_init(vorbis_comment *vc);
-extern void vorbis_comment_add(vorbis_comment *vc, char *comment);
-extern void vorbis_comment_add_tag(vorbis_comment *vc,
- char *tag, char *contents);
-extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count);
-extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag);
-extern void vorbis_comment_clear(vorbis_comment *vc);
-
-extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
-extern int vorbis_block_clear(vorbis_block *vb);
-extern void vorbis_dsp_clear(vorbis_dsp_state *v);
-
-/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
-
-extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi);
-extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op);
-extern int vorbis_analysis_headerout(vorbis_dsp_state *v,
- vorbis_comment *vc,
- ogg_packet *op,
- ogg_packet *op_comm,
- ogg_packet *op_code);
-extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals);
-extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals);
-extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb);
-extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op);
-
-extern int vorbis_bitrate_addblock(vorbis_block *vb);
-extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,
- ogg_packet *op);
-
-/* Vorbis PRIMITIVES: synthesis layer *******************************/
-extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,
- ogg_packet *op);
-
-extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi);
-extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op);
-extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op);
-extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb);
-extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm);
-extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
-extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
-
-/* Vorbis ERRORS and return codes ***********************************/
-
-#define OV_FALSE -1
-#define OV_EOF -2
-#define OV_HOLE -3
-
-#define OV_EREAD -128
-#define OV_EFAULT -129
-#define OV_EIMPL -130
-#define OV_EINVAL -131
-#define OV_ENOTVORBIS -132
-#define OV_EBADHEADER -133
-#define OV_EVERSION -134
-#define OV_ENOTAUDIO -135
-#define OV_EBADPACKET -136
-#define OV_EBADLINK -137
-#define OV_ENOSEEK -138
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif
-
+/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + + ******************************************************************** + + function: libvorbis codec headers + last mod: $Id: codec.h,v 1.2 2003-04-23 10:36:25 xovo Exp $ + + ********************************************************************/ + +#ifndef _vorbis_codec_h_ +#define _vorbis_codec_h_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include <ogg/ogg.h> + +typedef struct vorbis_info{ + int version; + int channels; + long rate; + + /* The below bitrate declarations are *hints*. + Combinations of the three values carry the following implications: + + all three set to the same value: + implies a fixed rate bitstream + only nominal set: + implies a VBR stream that averages the nominal bitrate. No hard + upper/lower limit + upper and or lower set: + implies a VBR bitstream that obeys the bitrate limits. nominal + may also be set to give a nominal rate. + none set: + the coder does not care to speculate. + */ + + long bitrate_upper; + long bitrate_nominal; + long bitrate_lower; + long bitrate_window; + + void *codec_setup; +} vorbis_info; + +/* vorbis_dsp_state buffers the current vorbis audio + analysis/synthesis state. The DSP state belongs to a specific + logical bitstream ****************************************************/ +typedef struct vorbis_dsp_state{ + int analysisp; + vorbis_info *vi; + + float **pcm; + float **pcmret; + int pcm_storage; + int pcm_current; + int pcm_returned; + + int preextrapolate; + int eofflag; + + long lW; + long W; + long nW; + long centerW; + + ogg_int64_t granulepos; + ogg_int64_t sequence; + + ogg_int64_t glue_bits; + ogg_int64_t time_bits; + ogg_int64_t floor_bits; + ogg_int64_t res_bits; + + void *backend_state; +} vorbis_dsp_state; + +typedef struct vorbis_block{ + /* necessary stream state for linking to the framing abstraction */ + float **pcm; /* this is a pointer into local storage */ + oggpack_buffer opb; + + long lW; + long W; + long nW; + int pcmend; + int mode; + + int eofflag; + ogg_int64_t granulepos; + ogg_int64_t sequence; + vorbis_dsp_state *vd; /* For read-only access of configuration */ + + /* local storage to avoid remallocing; it's up to the mapping to + structure it */ + void *localstore; + long localtop; + long localalloc; + long totaluse; + struct alloc_chain *reap; + + /* bitmetrics for the frame */ + long glue_bits; + long time_bits; + long floor_bits; + long res_bits; + + void *internal; + +} vorbis_block; + +/* vorbis_block is a single block of data to be processed as part of +the analysis/synthesis stream; it belongs to a specific logical +bitstream, but is independant from other vorbis_blocks belonging to +that logical bitstream. *************************************************/ + +struct alloc_chain{ + void *ptr; + struct alloc_chain *next; +}; + +/* vorbis_info contains all the setup information specific to the + specific compression/decompression mode in progress (eg, + psychoacoustic settings, channel setup, options, codebook + etc). vorbis_info and substructures are in backends.h. +*********************************************************************/ + +/* the comments are not part of vorbis_info so that vorbis_info can be + static storage */ +typedef struct vorbis_comment{ + /* unlimited user comment fields. libvorbis writes 'libvorbis' + whatever vendor is set to in encode */ + char **user_comments; + int *comment_lengths; + int comments; + char *vendor; + +} vorbis_comment; + + +/* libvorbis encodes in two abstraction layers; first we perform DSP + and produce a packet (see docs/analysis.txt). The packet is then + coded into a framed OggSquish bitstream by the second layer (see + docs/framing.txt). Decode is the reverse process; we sync/frame + the bitstream and extract individual packets, then decode the + packet back into PCM audio. + + The extra framing/packetizing is used in streaming formats, such as + files. Over the net (such as with UDP), the framing and + packetization aren't necessary as they're provided by the transport + and the streaming layer is not used */ + +/* Vorbis PRIMITIVES: general ***************************************/ + +extern void vorbis_info_init(vorbis_info *vi); +extern void vorbis_info_clear(vorbis_info *vi); +extern int vorbis_info_blocksize(vorbis_info *vi,int zo); +extern void vorbis_comment_init(vorbis_comment *vc); +extern void vorbis_comment_add(vorbis_comment *vc, char *comment); +extern void vorbis_comment_add_tag(vorbis_comment *vc, + char *tag, char *contents); +extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count); +extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag); +extern void vorbis_comment_clear(vorbis_comment *vc); + +extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb); +extern int vorbis_block_clear(vorbis_block *vb); +extern void vorbis_dsp_clear(vorbis_dsp_state *v); + +/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/ + +extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op); +extern int vorbis_analysis_headerout(vorbis_dsp_state *v, + vorbis_comment *vc, + ogg_packet *op, + ogg_packet *op_comm, + ogg_packet *op_code); +extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals); +extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op); + +extern int vorbis_bitrate_addblock(vorbis_block *vb); +extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, + ogg_packet *op); + +/* Vorbis PRIMITIVES: synthesis layer *******************************/ +extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc, + ogg_packet *op); + +extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi); +extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op); +extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb); +extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm); +extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples); +extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); + +/* Vorbis ERRORS and return codes ***********************************/ + +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 + +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 +#define OV_ENOTVORBIS -132 +#define OV_EBADHEADER -133 +#define OV_EVERSION -134 +#define OV_ENOTAUDIO -135 +#define OV_EBADPACKET -136 +#define OV_EBADLINK -137 +#define OV_ENOSEEK -138 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/oggwrite~/help-oggwrite~.pd b/oggwrite~/help-oggwrite~.pd index 86bbd91..8e9ca4b 100644 --- a/oggwrite~/help-oggwrite~.pd +++ b/oggwrite~/help-oggwrite~.pd @@ -1,59 +1,59 @@ -#N canvas 286 47 631 513 10;
-#X obj 40 415 oggwrite~;
-#X obj 40 64 osc~ 440;
-#X floatatom 40 33 5 0 0;
-#X msg 120 52 open myfile.ogg;
-#X msg 175 125 start;
-#X msg 185 148 stop;
-#X msg 155 78 append;
-#X msg 166 99 truncate;
-#X floatatom 89 441 5 0 0;
-#X floatatom 40 470 5 0 0;
-#X msg 204 259 print;
-#X text 189 180 vorbis <samplerate> <channles> <max.br> <nom.br> <min.br>
-;
-#X text 373 251 channels: 1 or 2 (default);
-#X text 204 216 vbr <samplerate> <channels> <quality>;
-#X msg 203 232 vbr 44100 2 0.4;
-#X text 324 238 quality settings: 0 - 1 (low - hi);
-#X text 325 267 resampling currently not supported!;
-#X text 202 290 comment <tag> <content>;
-#X text 204 329 possible tags: TITLE \, ARTIST \, PERFORMER \, DESCRIPTION
-\,;
-#X text 293 342 GENRE \, LOCATION \, COPYRIGHT \, CONTACT \, DATE;
-#X msg 202 307 ARTIST your=name;
-#X msg 189 197 vorbis 44100 2 144 128 96;
-#X text 136 441 ogg pages written to file;
-#X msg 481 455 \; pd dsp 1;
-#X msg 547 455 \; pd dsp 0;
-#X obj 481 429 loadbang;
-#X text 354 9 written by Olaf Matthes (olaf.matthes@gmx.de);
-#X text 353 21 get latest version at;
-#X text 354 34 http://www.akustische-kunst.de/puredata/;
-#X text 209 76 append data at end of file;
-#X text 226 97 overwrite previously recorded data;
-#X text 221 145 stop recording;
-#X text 225 50 open a file first!;
-#X text 240 407 might result in audible dropouts!;
-#X text 202 395 note: changing settings while recording;
-#X text 85 470 file state (1 = open \; 0 = closed);
-#X text 5 9 oggwrite~ version 0.1 - write Ogg Vorbis stream to file
-;
-#X msg 204 361 COPYRIGHT (c)=2002=Olaf=Matthes;
-#X text 220 123 start recording;
-#X connect 0 0 9 0;
-#X connect 0 1 8 0;
-#X connect 1 0 0 0;
-#X connect 1 0 0 1;
-#X connect 2 0 1 0;
-#X connect 3 0 0 0;
-#X connect 4 0 0 0;
-#X connect 5 0 0 0;
-#X connect 6 0 0 0;
-#X connect 7 0 0 0;
-#X connect 10 0 0 0;
-#X connect 14 0 0 0;
-#X connect 20 0 0 0;
-#X connect 21 0 0 0;
-#X connect 25 0 23 0;
-#X connect 37 0 0 0;
+#N canvas 286 47 631 513 10; +#X obj 40 415 oggwrite~; +#X obj 40 64 osc~ 440; +#X floatatom 40 33 5 0 0; +#X msg 120 52 open myfile.ogg; +#X msg 175 125 start; +#X msg 185 148 stop; +#X msg 155 78 append; +#X msg 166 99 truncate; +#X floatatom 89 441 5 0 0; +#X floatatom 40 470 5 0 0; +#X msg 204 259 print; +#X text 189 180 vorbis <samplerate> <channles> <max.br> <nom.br> <min.br> +; +#X text 373 251 channels: 1 or 2 (default); +#X text 204 216 vbr <samplerate> <channels> <quality>; +#X msg 203 232 vbr 44100 2 0.4; +#X text 324 238 quality settings: 0 - 1 (low - hi); +#X text 325 267 resampling currently not supported!; +#X text 202 290 comment <tag> <content>; +#X text 204 329 possible tags: TITLE \, ARTIST \, PERFORMER \, DESCRIPTION +\,; +#X text 293 342 GENRE \, LOCATION \, COPYRIGHT \, CONTACT \, DATE; +#X msg 202 307 ARTIST your=name; +#X msg 189 197 vorbis 44100 2 144 128 96; +#X text 136 441 ogg pages written to file; +#X msg 481 455 \; pd dsp 1; +#X msg 547 455 \; pd dsp 0; +#X obj 481 429 loadbang; +#X text 354 9 written by Olaf Matthes (olaf.matthes@gmx.de); +#X text 353 21 get latest version at; +#X text 354 34 http://www.akustische-kunst.de/puredata/; +#X text 209 76 append data at end of file; +#X text 226 97 overwrite previously recorded data; +#X text 221 145 stop recording; +#X text 225 50 open a file first!; +#X text 240 407 might result in audible dropouts!; +#X text 202 395 note: changing settings while recording; +#X text 85 470 file state (1 = open \; 0 = closed); +#X text 5 9 oggwrite~ version 0.1 - write Ogg Vorbis stream to file +; +#X msg 204 361 COPYRIGHT (c)=2002=Olaf=Matthes; +#X text 220 123 start recording; +#X connect 0 0 9 0; +#X connect 0 1 8 0; +#X connect 1 0 0 0; +#X connect 1 0 0 1; +#X connect 2 0 1 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X connect 10 0 0 0; +#X connect 14 0 0 0; +#X connect 20 0 0 0; +#X connect 21 0 0 0; +#X connect 25 0 23 0; +#X connect 37 0 0 0; diff --git a/oggwrite~/oggwrite~.c b/oggwrite~/oggwrite~.c index f9619de..552973c 100644 --- a/oggwrite~/oggwrite~.c +++ b/oggwrite~/oggwrite~.c @@ -1,751 +1,751 @@ -/* -------------------------- oggwrite~ ---------------------------------------- */
-/* */
-/* Tilde object to send ogg/vorbis encoded stream to icecast2 server. */
-/* Written by Olaf Matthes (olaf.matthes@gmx.de). */
-/* Get source at http://www.akustische-kunst.de/puredata/ */
-/* */
-/* This library is free software; you can redistribute it and/or */
-/* modify it under the terms of the GNU Lesser General Public */
-/* License as published by the Free Software Foundation; either */
-/* version 2 of the License, or (at your option) any later version. */
-/* */
-/* This library 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 */
-/* Lesser General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU Lesser General Public */
-/* License along with this library; 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 Ogg/Vorbis encoding library which can be found at */
-/* http://www.vorbis.org */
-/* */
-/* ---------------------------------------------------------------------------- */
-
-
-
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-
-#include <sys/types.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <malloc.h>
-#include <ctype.h>
-#include <time.h>
-#ifdef unix
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <sys/time.h>
-#define SOCKET_ERROR -1
-#else
-#include <io.h>
-#include <windows.h>
-#include <winsock.h>
-#include <windef.h>
-#endif
-
-#include "m_pd.h" /* standard pd stuff */
-#include "vorbisenc.h" /* vorbis encoder stuff */
-
-#define READ 1024 /* number of samples send to encoder at each call */
- /* has to be even multiple of 64 */
-
-static char *oggwrite_version = "oggwrite~: ogg/vorbis recorder version 0.1c, written by Olaf Matthes";
-
-static t_class *oggwrite_class;
-
-typedef struct _oggwrite
-{
- t_object x_obj;
- /* ogg/vorbis related stuff */
- ogg_stream_state x_os; /* take physical pages, weld into a logical stream of packets */
- ogg_page x_og; /* one Ogg bitstream page. Vorbis packets are inside */
- ogg_packet x_op; /* one raw packet of data for decode */
- vorbis_info x_vi; /* struct that stores all the static vorbis bitstream settings */
- vorbis_comment x_vc; /* struct that stores all the user comments */
- vorbis_dsp_state x_vd; /* central working state for the packet->PCM decoder */
- vorbis_block x_vb; /* local working space for packet->PCM decode */
-
- t_int x_eos; /* end of stream */
- t_int x_vorbis; /* info about encoder status */
- t_float x_pages; /* number of pages that have been output to server */
- t_outlet *x_outpages; /* output to send them to */
-
- /* ringbuffer stuff */
- t_float *x_buffer; /* data to be buffered (ringbuffer)*/
- t_int x_bytesbuffered; /* number of unprocessed bytes in buffer */
-
- /* ogg/vorbis format stuff */
- t_int x_samplerate; /* samplerate of stream (default = getsr() ) */
- t_float x_quality; /* desired quality level from 0.0 to 1.0 (lo to hi) */
- t_int x_br_max; /* max. bitrate of ogg/vorbis stream */
- t_int x_br_nom; /* nom. bitrate of ogg/vorbis stream */
- t_int x_br_min; /* min. bitrate of ogg/vorbis stream */
- t_int x_channels; /* number of channels (1 or 2) */
- t_int x_vbr;
-
- /* IceCast server stuff */
- char* x_passwd; /* password for server */
- char* x_bcname; /* name of broadcast */
- char* x_bcurl; /* url of broadcast */
- char* x_bcgenre; /* genre of broadcast */
- char* x_bcdescription; /* description */
- char* x_bcartist; /* artist */
- char* x_bclocation;
- char* x_bccopyright;
- char* x_bcperformer;
- char* x_bccontact;
- char* x_bcdate; /* system date when broadcast started */
- char* x_mountpoint; /* mountpoint for IceCast server */
- t_int x_bcpublic; /* do(n't) publish broadcast on www.oggwrite.com */
-
- /* recording stuff */
- t_int x_fd; /* file descriptor of the mp3 output */
- t_int x_file_open_mode;/* file opening mode */
- t_int x_byteswritten; /* number of bytes written */
- t_int x_recflag; /* recording flag toggled by messages "start" and "stop" */
-
- t_float x_f; /* float needed for signal input */
-} t_oggwrite;
-
-/* Utility functions */
-
-static void sys_closesocket(int fd)
-{
-#ifdef unix
- close(fd);
-#endif
-#ifdef NT
- closesocket(fd);
-#endif
-}
- /* prototypes */
-static void oggwrite_vorbis_deinit(t_oggwrite *x);
-
-/* ----------------------------------------- oggwrite~ ---------------------------------- */
- /* write ogg/vorbis to file */
-static int oggwrite_write(t_oggwrite *x)
-{
- int err = -1; /* error return code */
-
- /* write out pages (if any) */
- while(!x->x_eos)
- {
- int result=ogg_stream_pageout(&(x->x_os),&(x->x_og));
- if(result==0)break;
-#ifndef unix
- err = _write(x->x_fd, x->x_og.header, x->x_og.header_len);
-#else
- err = write(x->x_fd, x->x_og.header, x->x_og.header_len);
-#endif
- if(err < 0)
- {
- error("oggwrite~: could not send ogg header to server (%d)", err);
- x->x_eos = 1; /* indicate (artificial) end of stream */
- return err;
- }
-#ifndef unix
- err = _write(x->x_fd, x->x_og.body, x->x_og.body_len);
-#else
- err = write(x->x_fd, x->x_og.body, x->x_og.body_len);
-#endif
- if(err < 0)
- {
- error("oggwrite~: could not send ogg body to server (%d)", err);
- x->x_eos = 1; /* indicate (artificial) end of stream */
- return err;
- }
- x->x_pages++; /* count number of pages */
- /* there might be more than one pages we have to send */
- if(ogg_page_eos(&(x->x_og)))x->x_eos=1;
- }
- outlet_float(x->x_outpages, x->x_pages); /* update info */
- return 1;
-}
-
-
- /* encode data to ogg/vorbis stream */
-static void oggwrite_encode(t_oggwrite *x)
-{
- unsigned short i, ch;
- int err = 1;
- int n;
- int channel = x->x_channels; /* make lokal copy of num. of channels */
-
- /* expose the buffer to submit data */
- float **inbuffer=vorbis_analysis_buffer(&(x->x_vd),READ);
-
- /* read from buffer */
- for(n = 0; n < READ / channel; n++) /* fill encode buffer */
- {
- for(ch = 0; ch < channel; ch++)
- {
- inbuffer[ch][n] = (float)x->x_buffer[n * channel + ch];
- }
- }
- /* tell the library how much we actually submitted */
- vorbis_analysis_wrote(&(x->x_vd),n);
-
- /* vorbis does some data preanalysis, then divvies up blocks for
- more involved (potentially parallel) processing. Get a single
- block for encoding now */
- while(vorbis_analysis_blockout(&(x->x_vd),&(x->x_vb))==1)
- {
- /* analysis, assume we want to use bitrate management */
- vorbis_analysis(&(x->x_vb),NULL);
- vorbis_bitrate_addblock(&(x->x_vb));
-
- while(vorbis_bitrate_flushpacket(&(x->x_vd),&(x->x_op)))
- {
- /* weld the packet into the bitstream */
- ogg_stream_packetin(&(x->x_os),&(x->x_op));
- err = oggwrite_write(x); /* stream packet to server */
- }
- }
- /* check for errors */
- if(err < 0)
- {
- if(x->x_fd > 0)
- {
-#ifndef unix
- if(_close(x->x_fd) < 0)
-#else
- if(close(x->x_fd) < 0)
-#endif
- {
- post( "oggwrite~: file closed due to an error" );
- outlet_float(x->x_obj.ob_outlet, 0);
- }
- }
- }
-}
-
- /* buffer data as channel interleaved floats */
-static t_int *oggwrite_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_oggwrite *x = (t_oggwrite *)(w[3]);
- int n = (int)(w[4]); /* number of samples */
- int i;
- t_float in;
-
- /* copy the data into the buffer */
- if(x->x_channels != 1) /* everything but mono */
- {
- n *= 2; /* two channels go into one buffer */
-
- for(i = 0; i < n; i++)
- {
- if(i%2)
- {
- in = *(in2++); /* right inlet */
- }
- else
- {
- in = *(in1++); /* left inlet */
- }
- if (in > 1.0) { in = 1.0; }
- if (in < -1.0) { in = -1.0; }
- x->x_buffer[i + x->x_bytesbuffered] = in;
- }
- }
- else /* mono encoding -> just take left signal inlet 'in1' */
- {
- for(i = 0; i < n; i++)
- {
- in = *(in1++);
- if (in > 1.0) { in = 1.0; }
- if (in < -1.0) { in = -1.0; }
- x->x_buffer[i + x->x_bytesbuffered] = in;
- }
- }
- /* count, encode and send ogg/vorbis */
- if((x->x_fd >= 0)&&(x->x_recflag))
- {
- /* count buffered samples when connected */
- x->x_bytesbuffered += n;
-
- /* encode and send to server */
- if((x->x_bytesbuffered >= READ)&&(x->x_vorbis >= 0))
- {
- oggwrite_encode(x); /* encode data */
- x->x_bytesbuffered = 0; /* assume we got rid of all of them */
- }
- }
- return (w+5);
-}
-
-static void oggwrite_dsp(t_oggwrite *x, t_signal **sp)
-{
- dsp_add(oggwrite_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n);
-}
-
- /* initialize the vorbisenc library */
-static void oggwrite_vorbis_init(t_oggwrite *x)
-{
- int err = -1;
-
- x->x_vorbis = -1; /* indicate that encoder is not available right now */
-
- /* choose an encoding mode */
- vorbis_info_init(&(x->x_vi));
-
- if(x->x_samplerate != sys_getsr())post("oggwrite~: warning: resampling from %d to %.0f not supported", x->x_samplerate, sys_getsr());
- if(x->x_vbr == 1)
- { /* quality based setting */
- if(vorbis_encode_init_vbr(&(x->x_vi), x->x_channels, x->x_samplerate, x->x_quality))
- {
- post("oggwrite~: ogg/vorbis mode initialisation failed: invalid parameters for quality");
- vorbis_info_clear(&(x->x_vi));
- return;
- }
- }
- else
- { /* bitrate based setting */
- if(vorbis_encode_init(&(x->x_vi), x->x_channels, x->x_samplerate, x->x_br_max*1024, x->x_br_nom*1024, x->x_br_min*1024))
- {
- post("oggwrite~: ogg/vorbis mode initialisation failed: invalid parameters for quality");
- vorbis_info_clear(&(x->x_vi));
- return;
- }
- }
-
- /* add a comment */
- vorbis_comment_init(&(x->x_vc));
- vorbis_comment_add_tag(&(x->x_vc),"TITLE", x->x_bcname);
- vorbis_comment_add_tag(&(x->x_vc),"ARTIST", x->x_bcartist);
- vorbis_comment_add_tag(&(x->x_vc),"GENRE",x->x_bcgenre);
- vorbis_comment_add_tag(&(x->x_vc),"DESCRIPTION", x->x_bcdescription);
- vorbis_comment_add_tag(&(x->x_vc),"LOCATION",x->x_bclocation);
- vorbis_comment_add_tag(&(x->x_vc),"PERFORMER",x->x_bcperformer);
- vorbis_comment_add_tag(&(x->x_vc),"COPYRIGHT",x->x_bccopyright);
- vorbis_comment_add_tag(&(x->x_vc),"CONTACT",x->x_bccontact);
- vorbis_comment_add_tag(&(x->x_vc),"DATE",x->x_bcdate);
- vorbis_comment_add_tag(&(x->x_vc),"ENCODER","oggwrite~ v0.1b for pure-data");
-
- /* set up the analysis state and auxiliary encoding storage */
- vorbis_analysis_init(&(x->x_vd),&(x->x_vi));
- vorbis_block_init(&(x->x_vd),&(x->x_vb));
-
- /* set up our packet->stream encoder */
- /* pick a random serial number; that way we can more likely build
- chained streams just by concatenation */
- srand(time(NULL));
- ogg_stream_init(&(x->x_os),rand());
-
- /* Vorbis streams begin with three headers; the initial header (with
- most of the codec setup parameters) which is mandated by the Ogg
- bitstream spec. The second header holds any comment fields. The
- third header holds the bitstream codebook. We merely need to
- make the headers, then pass them to libvorbis one at a time;
- libvorbis handles the additional Ogg bitstream constraints */
-
- {
- ogg_packet header;
- ogg_packet header_comm;
- ogg_packet header_code;
-
- vorbis_analysis_headerout(&(x->x_vd),&(x->x_vc),&header,&header_comm,&header_code);
- ogg_stream_packetin(&(x->x_os),&header); /* automatically placed in its own page */
- ogg_stream_packetin(&(x->x_os),&header_comm);
- ogg_stream_packetin(&(x->x_os),&header_code);
-
- /* We don't have to write out here, but doing so makes streaming
- * much easier, so we do, flushing ALL pages. This ensures the actual
- * audio data will start on a new page
- *
- * IceCast2 server will take this as a first info about our stream
- */
- while(!x->x_eos)
- {
- int result=ogg_stream_flush(&(x->x_os),&(x->x_og));
- if(result==0)break;
-#ifndef unix
- err = _write(x->x_fd, x->x_og.header, x->x_og.header_len);
-#else
- err = write(x->x_fd, x->x_og.header, x->x_og.header_len);
-#endif
- if(err < 0)
- {
- error("oggwrite~: could not write ogg header to file (%d)", err);
- x->x_eos = 1; /* indicate end of stream */
- x->x_vorbis = -1; /* stop encoding instantly */
- if(x->x_fd > 0)
- {
-#ifndef unix
- if(_close(x->x_fd) < 0)
-#else
- if(close(x->x_fd) < 0)
-#endif
- {
- post( "oggwrite~: file closed due to an error" );
- outlet_float(x->x_obj.ob_outlet, 0);
- }
- }
- return;
- }
-#ifndef unix
- err = _write(x->x_fd, x->x_og.body, x->x_og.body_len);
-#else
- err = write(x->x_fd, x->x_og.body, x->x_og.body_len);
-#endif
- if(err < 0)
- {
- error("oggwrite~: could not write ogg body to file (%d)", err);
- x->x_eos = 1; /* indicate end of stream */
- x->x_vorbis = -1; /* stop encoding instantly */
- if(x->x_fd > 0)
- {
-#ifndef unix
- if(_close(x->x_fd) < 0)
-#else
- if(close(x->x_fd) < 0)
-#endif
- {
- post( "oggwrite~: file closed due to an error" );
- outlet_float(x->x_obj.ob_outlet, 0);
- }
- }
- return;
- }
- }
- }
- x->x_vorbis = 1; /* vorbis encoder initialised */
- post("oggwrite~: ogg/vorbis encoder (re)initialised");
-}
-
- /* initialize the vorbisenc library */
-static void oggwrite_vorbis_deinit(t_oggwrite *x)
-{
- x->x_vorbis = -1;
- vorbis_analysis_wrote(&(x->x_vd),0);
- /* clean up and exit. vorbis_info_clear() must be called last */
- ogg_stream_clear(&(x->x_os));
- vorbis_block_clear(&(x->x_vb));
- vorbis_dsp_clear(&(x->x_vd));
- vorbis_comment_clear(&(x->x_vc));
- vorbis_info_clear(&(x->x_vi));
- post("oggwrite~: ogg/vorbis encoder closed");
-}
-
- /* connect to oggwrite server */
-static void oggwrite_open(t_oggwrite *x, t_symbol *sfile)
-{
- time_t now; /* to get the time */
-
- /* closing previous file descriptor */
- if(x->x_fd > 0)
- {
-#ifndef unix
- if(_close(x->x_fd) < 0)
-#else
- if(close(x->x_fd) < 0)
-#endif
- {
- error( "oggwrite~: file closed" );
- outlet_float(x->x_obj.ob_outlet, 0);
- }
- }
-
- if(x->x_recflag)
- {
- x->x_recflag = 0;
- }
-
-#ifndef unix
- if((x->x_fd = _open( sfile->s_name, x->x_file_open_mode, _S_IREAD|_S_IWRITE)) < 0)
-#else
- if((x->x_fd = open( sfile->s_name, x->x_file_open_mode, S_IRWXU|S_IRWXG|S_IRWXO )) < 0)
-#endif
- {
- error( "oggwrite~: can not open \"%s\"", sfile->s_name);
- x->x_fd=-1;
- return;
- }
- x->x_byteswritten = 0;
- post( "oggwrite~: \"%s \" opened", sfile->s_name);
- outlet_float(x->x_obj.ob_outlet, 1);
-
- /* get the time for the DATE comment, then init encoder */
- now=time(NULL);
- x->x_bcdate = ctime(&now);
-
- x->x_eos = 0;
- oggwrite_vorbis_init(x);
-}
-
- /* setting file write mode to append */
-static void oggwrite_append(t_oggwrite *x)
-{
-#ifndef unix
- x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_APPEND|_O_BINARY;
-#else
- x->x_file_open_mode = O_CREAT|O_WRONLY|O_APPEND|O_NONBLOCK;
-#endif
- if(x->x_fd>=0)post("oggwrite~: mode set to append: open a new file to make changes take effect");
-}
-
- /* setting file write mode to truncate */
-static void oggwrite_truncate(t_oggwrite *x)
-{
-#ifndef unix
- x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_TRUNC|_O_BINARY;
-#else
- x->x_file_open_mode = O_CREAT|O_WRONLY|O_TRUNC|O_NONBLOCK;
-#endif
- if(x->x_fd>=0)post("oggwrite~: mode set to truncate: open a new file to make changes take effect");
-}
-
- /* start recording */
-static void oggwrite_start(t_oggwrite *x)
-{
- if ( x->x_fd < 0 ) {
- post("oggwrite~: no file selected");
- return;
- }
-
- if ( x->x_recflag == 1 ) {
- post("oggwrite~: already recording");
- return;
- }
- if(x->x_vorbis < 0)
- {
- oggwrite_vorbis_init(x);
- }
-
- x->x_recflag = 1;
- post("oggwrite~: start recording");
-}
-
- /* stop recording */
-static void oggwrite_stop(t_oggwrite *x)
-{
- int err = -1;
-
- /* first stop recording / buffering and so on, than do the rest */
- x->x_recflag = 0;
- post("oggwrite~: recording stoped");
- if(x->x_vorbis >= 0)
- {
- oggwrite_vorbis_deinit(x);
- }
-}
-
- /* set comment fields for header (reads in just anything) */
-static void oggwrite_comment(t_oggwrite *x, t_symbol *s, t_int argc, t_atom* argv)
-{
- int i = argc;
- char *comment = NULL;
- int len = strlen(atom_gensym(argv)->s_name);
-
- comment = atom_gensym(argv)->s_name;
-
- while (len--)
- {
- if(*(comment + len) == '=')*(comment + len) = ' ';
- }
-
- if(strstr(s->s_name, "ARTIST"))
- {
- x->x_bcartist = comment;
- post("oggwrite~: ARTIST = %s", x->x_bcartist);
- }
- else if(strstr(s->s_name, "GENRE"))
- {
- x->x_bcgenre = comment;
- post("oggwrite~: GENRE = %s", x->x_bcgenre);
- }
- else if(strstr(s->s_name, "TITLE"))
- {
- x->x_bcname = comment;
- post("oggwrite~: TITLE = %s", x->x_bcname);
- }
- else if(strstr(s->s_name, "PERFORMER"))
- {
- x->x_bcperformer = comment;
- post("oggwrite~: PERFORMER = %s", x->x_bcperformer);
- }
- else if(strstr(s->s_name, "LOCATION"))
- {
- x->x_bclocation = comment;
- post("oggwrite~: LOCATION = %s", x->x_bclocation);
- }
- else if(strstr(s->s_name, "COPYRIGHT"))
- {
- x->x_bccopyright = comment;
- post("oggwrite~: COPYRIGHT = %s", x->x_bccopyright);
- }
- else if(strstr(s->s_name, "CONTACT"))
- {
- x->x_bccontact = comment;
- post("oggwrite~: CONTACT = %s", x->x_bccontact);
- }
- else if(strstr(s->s_name, "DESCRIPTION"))
- {
- x->x_bcdescription = comment;
- post("oggwrite~: DESCRIPTION = %s", x->x_bcdescription);
- }
- else if(strstr(s->s_name, "DATE"))
- {
- x->x_bcdate = comment;
- post("oggwrite~: DATE=%s", x->x_bcdate);
- }
- else post("oggwrite~: no method for %s", s->s_name);
- if(x->x_vorbis >=0)
- {
- oggwrite_vorbis_deinit(x);
- oggwrite_vorbis_init(x);
- }
-}
-
- /* settings for variable bitrate encoding */
-static void oggwrite_vbr(t_oggwrite *x, t_floatarg fsr, t_floatarg fchannels,
- t_floatarg fquality)
-{
- x->x_vbr = 1;
- x->x_samplerate = (t_int)fsr;
- x->x_quality = fquality;
- x->x_channels = (t_int)fchannels;
- post("oggwrite~: %d channels @ %d Hz, quality %.2f", x->x_channels, x->x_samplerate, x->x_quality);
- if(x->x_vorbis >=0)
- {
- oggwrite_vorbis_deinit(x);
- oggwrite_vorbis_init(x);
- }
-}
-
- /* settings for bitrate-based vbr encoding */
-static void oggwrite_vorbis(t_oggwrite *x, t_floatarg fsr, t_floatarg fchannels,
- t_floatarg fmax, t_floatarg fnom, t_floatarg fmin)
-{
- x->x_vbr = 0;
- x->x_samplerate = (t_int)fsr;
- x->x_channels = (t_int)fchannels;
- x->x_br_max = (t_int)fmax;
- x->x_br_nom = (t_int)fnom;
- x->x_br_min = (t_int)fmin;
- post("oggwrite~: %d channels @ %d Hz, bitrates: max. %d / nom. %d / min. %d",
- x->x_channels, x->x_samplerate, x->x_br_max, x->x_br_nom, x->x_br_min);
- if(x->x_vorbis >=0)
- {
- oggwrite_vorbis_deinit(x);
- oggwrite_vorbis_init(x);
- }
-}
-
- /* print settings to pd's console window */
-static void oggwrite_print(t_oggwrite *x)
-{
- if(x->x_vbr == 1)
- {
- post("oggwrite~: Ogg Vorbis encoder: %d channels @ %d Hz, quality %.2f", x->x_channels, x->x_samplerate, x->x_quality);
- }
- else
- {
- post("oggwrite~: Ogg Vorbis encoder: %d channels @ %d Hz, bitrates: max. %d, nom. %d, min. %d",
- x->x_channels, x->x_samplerate, x->x_br_max, x->x_br_nom, x->x_br_min);
- }
- post("oggwrite~: Ogg Vorbis comments:");
- post(" TITLE = %s", x->x_bcname);
- post(" ARTIST = %s", x->x_bcartist);
- post(" PERFORMER = %s", x->x_bcperformer);
- post(" GENRE = %s", x->x_bcgenre);
- post(" LOCATION = %s", x->x_bclocation);
- post(" COPYRIGHT = %s", x->x_bccopyright);
- post(" CONTACT = %s", x->x_bccontact);
- post(" DESCRIPTION = %s", x->x_bcdescription);
- post(" DATE = %s", x->x_bcdate);
-}
-
-
- /* clean up */
-static void oggwrite_free(t_oggwrite *x)
-{
- if(x->x_vorbis >= 0) /* close encoder */
- {
- oggwrite_vorbis_deinit(x);
- }
- if(x->x_fd >= 0)
- { /* close file */
-#ifndef unix
- _close(x->x_fd);
-#else
- close(x->x_fd);
-#endif
- outlet_float(x->x_obj.ob_outlet, 0);
- }
- freebytes(x->x_buffer, READ*sizeof(t_float));
-}
-
-static void *oggwrite_new(void)
-{
- t_oggwrite *x = (t_oggwrite *)pd_new(oggwrite_class);
- inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal"));
- outlet_new(&x->x_obj, gensym("float"));
- x->x_outpages = outlet_new(&x->x_obj, gensym("float"));
- x->x_fd = -1;
-#ifndef unix
- x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_APPEND|_O_BINARY;
-#else
- x->x_file_open_mode = O_CREAT|O_WRONLY|O_APPEND|O_NONBLOCK;
-#endif
- x->x_vorbis = -1;
- x->x_eos = 0;
- x->x_vbr = 1; /* use the vbr setting by default */
- x->x_samplerate = sys_getsr(); /* no resampling supported, sorry */
- x->x_quality = 0.4; /* quality 0.4 gives roughly 128kbps VBR stream */
- x->x_channels = 2; /* stereo */
- x->x_br_max = 144;
- x->x_br_nom = 128;
- x->x_br_min = 96;
- x->x_buffer = getbytes(READ*sizeof(t_float));
- if (!x->x_buffer) /* check buffer */
- {
- error("out of memory!");
- }
- x->x_bytesbuffered = 0;
- x->x_pages = 0;
- x->x_bcname = "ogg/vorbis stream";
- x->x_bcurl = "http://www.pure-data.org/";
- x->x_bcgenre = "experimental";
- x->x_bcdescription = "ogg/vorbis stream recorded with pure-data using oggwrite~";
- x->x_bcartist = "pure-data";
- x->x_bclocation = x->x_bcurl;
- x->x_bccopyright = "";
- x->x_bcperformer = "";
- x->x_bccontact = "";
- x->x_bcdate = "";
- post(oggwrite_version);
- return(x);
-}
-
-void oggwrite_tilde_setup(void)
-{
- oggwrite_class = class_new(gensym("oggwrite~"), (t_newmethod)oggwrite_new, (t_method)oggwrite_free,
- sizeof(t_oggwrite), 0, 0);
- CLASS_MAINSIGNALIN(oggwrite_class, t_oggwrite, x_f );
- class_sethelpsymbol(oggwrite_class, gensym("help-oggwrite~.pd"));
- class_addmethod(oggwrite_class, (t_method)oggwrite_dsp, gensym("dsp"), 0);
- class_addmethod(oggwrite_class, (t_method)oggwrite_open, gensym("open"), A_SYMBOL, 0);
- class_addmethod(oggwrite_class, (t_method)oggwrite_start, gensym("start"), 0);
- class_addmethod(oggwrite_class, (t_method)oggwrite_stop, gensym("stop"), 0);
- class_addmethod(oggwrite_class, (t_method)oggwrite_append, gensym("append"), 0);
- class_addmethod(oggwrite_class, (t_method)oggwrite_truncate, gensym("truncate"), 0);
- class_addmethod(oggwrite_class, (t_method)oggwrite_vorbis, gensym("vorbis"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
- class_addmethod(oggwrite_class, (t_method)oggwrite_vbr, gensym("vbr"), A_FLOAT, A_FLOAT, A_FLOAT, 0);
- class_addmethod(oggwrite_class, (t_method)oggwrite_print, gensym("print"), 0);
- class_addanything(oggwrite_class, oggwrite_comment);
-}
+/* -------------------------- oggwrite~ ---------------------------------------- */ +/* */ +/* Tilde object to send ogg/vorbis encoded stream to icecast2 server. */ +/* Written by Olaf Matthes (olaf.matthes@gmx.de). */ +/* Get source at http://www.akustische-kunst.de/puredata/ */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Lesser General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2 of the License, or (at your option) any later version. */ +/* */ +/* This library 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 */ +/* Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public */ +/* License along with this library; 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 Ogg/Vorbis encoding library which can be found at */ +/* http://www.vorbis.org */ +/* */ +/* ---------------------------------------------------------------------------- */ + + + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include <sys/types.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <malloc.h> +#include <ctype.h> +#include <time.h> +#ifdef UNIX +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/time.h> +#define SOCKET_ERROR -1 +#else +#include <io.h> +#include <windows.h> +#include <winsock.h> +#include <windef.h> +#endif + +#include "m_pd.h" /* standard pd stuff */ +#include "vorbisenc.h" /* vorbis encoder stuff */ + +#define READ 1024 /* number of samples send to encoder at each call */ + /* has to be even multiple of 64 */ + +static char *oggwrite_version = "oggwrite~: ogg/vorbis recorder version 0.1c, written by Olaf Matthes"; + +static t_class *oggwrite_class; + +typedef struct _oggwrite +{ + t_object x_obj; + /* ogg/vorbis related stuff */ + ogg_stream_state x_os; /* take physical pages, weld into a logical stream of packets */ + ogg_page x_og; /* one Ogg bitstream page. Vorbis packets are inside */ + ogg_packet x_op; /* one raw packet of data for decode */ + vorbis_info x_vi; /* struct that stores all the static vorbis bitstream settings */ + vorbis_comment x_vc; /* struct that stores all the user comments */ + vorbis_dsp_state x_vd; /* central working state for the packet->PCM decoder */ + vorbis_block x_vb; /* local working space for packet->PCM decode */ + + t_int x_eos; /* end of stream */ + t_int x_vorbis; /* info about encoder status */ + t_float x_pages; /* number of pages that have been output to server */ + t_outlet *x_outpages; /* output to send them to */ + + /* ringbuffer stuff */ + t_float *x_buffer; /* data to be buffered (ringbuffer)*/ + t_int x_bytesbuffered; /* number of unprocessed bytes in buffer */ + + /* ogg/vorbis format stuff */ + t_int x_samplerate; /* samplerate of stream (default = getsr() ) */ + t_float x_quality; /* desired quality level from 0.0 to 1.0 (lo to hi) */ + t_int x_br_max; /* max. bitrate of ogg/vorbis stream */ + t_int x_br_nom; /* nom. bitrate of ogg/vorbis stream */ + t_int x_br_min; /* min. bitrate of ogg/vorbis stream */ + t_int x_channels; /* number of channels (1 or 2) */ + t_int x_vbr; + + /* IceCast server stuff */ + char* x_passwd; /* password for server */ + char* x_bcname; /* name of broadcast */ + char* x_bcurl; /* url of broadcast */ + char* x_bcgenre; /* genre of broadcast */ + char* x_bcdescription; /* description */ + char* x_bcartist; /* artist */ + char* x_bclocation; + char* x_bccopyright; + char* x_bcperformer; + char* x_bccontact; + char* x_bcdate; /* system date when broadcast started */ + char* x_mountpoint; /* mountpoint for IceCast server */ + t_int x_bcpublic; /* do(n't) publish broadcast on www.oggwrite.com */ + + /* recording stuff */ + t_int x_fd; /* file descriptor of the mp3 output */ + t_int x_file_open_mode;/* file opening mode */ + t_int x_byteswritten; /* number of bytes written */ + t_int x_recflag; /* recording flag toggled by messages "start" and "stop" */ + + t_float x_f; /* float needed for signal input */ +} t_oggwrite; + +/* Utility functions */ + +static void sys_closesocket(int fd) +{ +#ifdef UNIX + close(fd); +#endif +#ifdef NT + closesocket(fd); +#endif +} + /* prototypes */ +static void oggwrite_vorbis_deinit(t_oggwrite *x); + +/* ----------------------------------------- oggwrite~ ---------------------------------- */ + /* write ogg/vorbis to file */ +static int oggwrite_write(t_oggwrite *x) +{ + int err = -1; /* error return code */ + + /* write out pages (if any) */ + while(!x->x_eos) + { + int result=ogg_stream_pageout(&(x->x_os),&(x->x_og)); + if(result==0)break; +#ifndef UNIX + err = _write(x->x_fd, x->x_og.header, x->x_og.header_len); +#else + err = write(x->x_fd, x->x_og.header, x->x_og.header_len); +#endif + if(err < 0) + { + error("oggwrite~: could not send ogg header to server (%d)", err); + x->x_eos = 1; /* indicate (artificial) end of stream */ + return err; + } +#ifndef UNIX + err = _write(x->x_fd, x->x_og.body, x->x_og.body_len); +#else + err = write(x->x_fd, x->x_og.body, x->x_og.body_len); +#endif + if(err < 0) + { + error("oggwrite~: could not send ogg body to server (%d)", err); + x->x_eos = 1; /* indicate (artificial) end of stream */ + return err; + } + x->x_pages++; /* count number of pages */ + /* there might be more than one pages we have to send */ + if(ogg_page_eos(&(x->x_og)))x->x_eos=1; + } + outlet_float(x->x_outpages, x->x_pages); /* update info */ + return 1; +} + + + /* encode data to ogg/vorbis stream */ +static void oggwrite_encode(t_oggwrite *x) +{ + unsigned short i, ch; + int err = 1; + int n; + int channel = x->x_channels; /* make lokal copy of num. of channels */ + + /* expose the buffer to submit data */ + float **inbuffer=vorbis_analysis_buffer(&(x->x_vd),READ); + + /* read from buffer */ + for(n = 0; n < READ / channel; n++) /* fill encode buffer */ + { + for(ch = 0; ch < channel; ch++) + { + inbuffer[ch][n] = (float)x->x_buffer[n * channel + ch]; + } + } + /* tell the library how much we actually submitted */ + vorbis_analysis_wrote(&(x->x_vd),n); + + /* vorbis does some data preanalysis, then divvies up blocks for + more involved (potentially parallel) processing. Get a single + block for encoding now */ + while(vorbis_analysis_blockout(&(x->x_vd),&(x->x_vb))==1) + { + /* analysis, assume we want to use bitrate management */ + vorbis_analysis(&(x->x_vb),NULL); + vorbis_bitrate_addblock(&(x->x_vb)); + + while(vorbis_bitrate_flushpacket(&(x->x_vd),&(x->x_op))) + { + /* weld the packet into the bitstream */ + ogg_stream_packetin(&(x->x_os),&(x->x_op)); + err = oggwrite_write(x); /* stream packet to server */ + } + } + /* check for errors */ + if(err < 0) + { + if(x->x_fd > 0) + { +#ifndef UNIX + if(_close(x->x_fd) < 0) +#else + if(close(x->x_fd) < 0) +#endif + { + post( "oggwrite~: file closed due to an error" ); + outlet_float(x->x_obj.ob_outlet, 0); + } + } + } +} + + /* buffer data as channel interleaved floats */ +static t_int *oggwrite_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_oggwrite *x = (t_oggwrite *)(w[3]); + int n = (int)(w[4]); /* number of samples */ + int i; + t_float in; + + /* copy the data into the buffer */ + if(x->x_channels != 1) /* everything but mono */ + { + n *= 2; /* two channels go into one buffer */ + + for(i = 0; i < n; i++) + { + if(i%2) + { + in = *(in2++); /* right inlet */ + } + else + { + in = *(in1++); /* left inlet */ + } + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[i + x->x_bytesbuffered] = in; + } + } + else /* mono encoding -> just take left signal inlet 'in1' */ + { + for(i = 0; i < n; i++) + { + in = *(in1++); + if (in > 1.0) { in = 1.0; } + if (in < -1.0) { in = -1.0; } + x->x_buffer[i + x->x_bytesbuffered] = in; + } + } + /* count, encode and send ogg/vorbis */ + if((x->x_fd >= 0)&&(x->x_recflag)) + { + /* count buffered samples when connected */ + x->x_bytesbuffered += n; + + /* encode and send to server */ + if((x->x_bytesbuffered >= READ)&&(x->x_vorbis >= 0)) + { + oggwrite_encode(x); /* encode data */ + x->x_bytesbuffered = 0; /* assume we got rid of all of them */ + } + } + return (w+5); +} + +static void oggwrite_dsp(t_oggwrite *x, t_signal **sp) +{ + dsp_add(oggwrite_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); +} + + /* initialize the vorbisenc library */ +static void oggwrite_vorbis_init(t_oggwrite *x) +{ + int err = -1; + + x->x_vorbis = -1; /* indicate that encoder is not available right now */ + + /* choose an encoding mode */ + vorbis_info_init(&(x->x_vi)); + + if(x->x_samplerate != sys_getsr())post("oggwrite~: warning: resampling from %d to %.0f not supported", x->x_samplerate, sys_getsr()); + if(x->x_vbr == 1) + { /* quality based setting */ + if(vorbis_encode_init_vbr(&(x->x_vi), x->x_channels, x->x_samplerate, x->x_quality)) + { + post("oggwrite~: ogg/vorbis mode initialisation failed: invalid parameters for quality"); + vorbis_info_clear(&(x->x_vi)); + return; + } + } + else + { /* bitrate based setting */ + if(vorbis_encode_init(&(x->x_vi), x->x_channels, x->x_samplerate, x->x_br_max*1024, x->x_br_nom*1024, x->x_br_min*1024)) + { + post("oggwrite~: ogg/vorbis mode initialisation failed: invalid parameters for quality"); + vorbis_info_clear(&(x->x_vi)); + return; + } + } + + /* add a comment */ + vorbis_comment_init(&(x->x_vc)); + vorbis_comment_add_tag(&(x->x_vc),"TITLE", x->x_bcname); + vorbis_comment_add_tag(&(x->x_vc),"ARTIST", x->x_bcartist); + vorbis_comment_add_tag(&(x->x_vc),"GENRE",x->x_bcgenre); + vorbis_comment_add_tag(&(x->x_vc),"DESCRIPTION", x->x_bcdescription); + vorbis_comment_add_tag(&(x->x_vc),"LOCATION",x->x_bclocation); + vorbis_comment_add_tag(&(x->x_vc),"PERFORMER",x->x_bcperformer); + vorbis_comment_add_tag(&(x->x_vc),"COPYRIGHT",x->x_bccopyright); + vorbis_comment_add_tag(&(x->x_vc),"CONTACT",x->x_bccontact); + vorbis_comment_add_tag(&(x->x_vc),"DATE",x->x_bcdate); + vorbis_comment_add_tag(&(x->x_vc),"ENCODER","oggwrite~ v0.1b for pure-data"); + + /* set up the analysis state and auxiliary encoding storage */ + vorbis_analysis_init(&(x->x_vd),&(x->x_vi)); + vorbis_block_init(&(x->x_vd),&(x->x_vb)); + + /* set up our packet->stream encoder */ + /* pick a random serial number; that way we can more likely build + chained streams just by concatenation */ + srand(time(NULL)); + ogg_stream_init(&(x->x_os),rand()); + + /* Vorbis streams begin with three headers; the initial header (with + most of the codec setup parameters) which is mandated by the Ogg + bitstream spec. The second header holds any comment fields. The + third header holds the bitstream codebook. We merely need to + make the headers, then pass them to libvorbis one at a time; + libvorbis handles the additional Ogg bitstream constraints */ + + { + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_analysis_headerout(&(x->x_vd),&(x->x_vc),&header,&header_comm,&header_code); + ogg_stream_packetin(&(x->x_os),&header); /* automatically placed in its own page */ + ogg_stream_packetin(&(x->x_os),&header_comm); + ogg_stream_packetin(&(x->x_os),&header_code); + + /* We don't have to write out here, but doing so makes streaming + * much easier, so we do, flushing ALL pages. This ensures the actual + * audio data will start on a new page + * + * IceCast2 server will take this as a first info about our stream + */ + while(!x->x_eos) + { + int result=ogg_stream_flush(&(x->x_os),&(x->x_og)); + if(result==0)break; +#ifndef UNIX + err = _write(x->x_fd, x->x_og.header, x->x_og.header_len); +#else + err = write(x->x_fd, x->x_og.header, x->x_og.header_len); +#endif + if(err < 0) + { + error("oggwrite~: could not write ogg header to file (%d)", err); + x->x_eos = 1; /* indicate end of stream */ + x->x_vorbis = -1; /* stop encoding instantly */ + if(x->x_fd > 0) + { +#ifndef UNIX + if(_close(x->x_fd) < 0) +#else + if(close(x->x_fd) < 0) +#endif + { + post( "oggwrite~: file closed due to an error" ); + outlet_float(x->x_obj.ob_outlet, 0); + } + } + return; + } +#ifndef UNIX + err = _write(x->x_fd, x->x_og.body, x->x_og.body_len); +#else + err = write(x->x_fd, x->x_og.body, x->x_og.body_len); +#endif + if(err < 0) + { + error("oggwrite~: could not write ogg body to file (%d)", err); + x->x_eos = 1; /* indicate end of stream */ + x->x_vorbis = -1; /* stop encoding instantly */ + if(x->x_fd > 0) + { +#ifndef UNIX + if(_close(x->x_fd) < 0) +#else + if(close(x->x_fd) < 0) +#endif + { + post( "oggwrite~: file closed due to an error" ); + outlet_float(x->x_obj.ob_outlet, 0); + } + } + return; + } + } + } + x->x_vorbis = 1; /* vorbis encoder initialised */ + post("oggwrite~: ogg/vorbis encoder (re)initialised"); +} + + /* initialize the vorbisenc library */ +static void oggwrite_vorbis_deinit(t_oggwrite *x) +{ + x->x_vorbis = -1; + vorbis_analysis_wrote(&(x->x_vd),0); + /* clean up and exit. vorbis_info_clear() must be called last */ + ogg_stream_clear(&(x->x_os)); + vorbis_block_clear(&(x->x_vb)); + vorbis_dsp_clear(&(x->x_vd)); + vorbis_comment_clear(&(x->x_vc)); + vorbis_info_clear(&(x->x_vi)); + post("oggwrite~: ogg/vorbis encoder closed"); +} + + /* connect to oggwrite server */ +static void oggwrite_open(t_oggwrite *x, t_symbol *sfile) +{ + time_t now; /* to get the time */ + + /* closing previous file descriptor */ + if(x->x_fd > 0) + { +#ifndef UNIX + if(_close(x->x_fd) < 0) +#else + if(close(x->x_fd) < 0) +#endif + { + error( "oggwrite~: file closed" ); + outlet_float(x->x_obj.ob_outlet, 0); + } + } + + if(x->x_recflag) + { + x->x_recflag = 0; + } + +#ifndef UNIX + if((x->x_fd = _open( sfile->s_name, x->x_file_open_mode, _S_IREAD|_S_IWRITE)) < 0) +#else + if((x->x_fd = open( sfile->s_name, x->x_file_open_mode, S_IRWXU|S_IRWXG|S_IRWXO )) < 0) +#endif + { + error( "oggwrite~: can not open \"%s\"", sfile->s_name); + x->x_fd=-1; + return; + } + x->x_byteswritten = 0; + post( "oggwrite~: \"%s \" opened", sfile->s_name); + outlet_float(x->x_obj.ob_outlet, 1); + + /* get the time for the DATE comment, then init encoder */ + now=time(NULL); + x->x_bcdate = ctime(&now); + + x->x_eos = 0; + oggwrite_vorbis_init(x); +} + + /* setting file write mode to append */ +static void oggwrite_append(t_oggwrite *x) +{ +#ifndef UNIX + x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_APPEND|_O_BINARY; +#else + x->x_file_open_mode = O_CREAT|O_WRONLY|O_APPEND|O_NONBLOCK; +#endif + if(x->x_fd>=0)post("oggwrite~: mode set to append: open a new file to make changes take effect"); +} + + /* setting file write mode to truncate */ +static void oggwrite_truncate(t_oggwrite *x) +{ +#ifndef UNIX + x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_TRUNC|_O_BINARY; +#else + x->x_file_open_mode = O_CREAT|O_WRONLY|O_TRUNC|O_NONBLOCK; +#endif + if(x->x_fd>=0)post("oggwrite~: mode set to truncate: open a new file to make changes take effect"); +} + + /* start recording */ +static void oggwrite_start(t_oggwrite *x) +{ + if ( x->x_fd < 0 ) { + post("oggwrite~: no file selected"); + return; + } + + if ( x->x_recflag == 1 ) { + post("oggwrite~: already recording"); + return; + } + if(x->x_vorbis < 0) + { + oggwrite_vorbis_init(x); + } + + x->x_recflag = 1; + post("oggwrite~: start recording"); +} + + /* stop recording */ +static void oggwrite_stop(t_oggwrite *x) +{ + int err = -1; + + /* first stop recording / buffering and so on, than do the rest */ + x->x_recflag = 0; + post("oggwrite~: recording stoped"); + if(x->x_vorbis >= 0) + { + oggwrite_vorbis_deinit(x); + } +} + + /* set comment fields for header (reads in just anything) */ +static void oggwrite_comment(t_oggwrite *x, t_symbol *s, t_int argc, t_atom* argv) +{ + int i = argc; + char *comment = NULL; + int len = strlen(atom_gensym(argv)->s_name); + + comment = atom_gensym(argv)->s_name; + + while (len--) + { + if(*(comment + len) == '=')*(comment + len) = ' '; + } + + if(strstr(s->s_name, "ARTIST")) + { + x->x_bcartist = comment; + post("oggwrite~: ARTIST = %s", x->x_bcartist); + } + else if(strstr(s->s_name, "GENRE")) + { + x->x_bcgenre = comment; + post("oggwrite~: GENRE = %s", x->x_bcgenre); + } + else if(strstr(s->s_name, "TITLE")) + { + x->x_bcname = comment; + post("oggwrite~: TITLE = %s", x->x_bcname); + } + else if(strstr(s->s_name, "PERFORMER")) + { + x->x_bcperformer = comment; + post("oggwrite~: PERFORMER = %s", x->x_bcperformer); + } + else if(strstr(s->s_name, "LOCATION")) + { + x->x_bclocation = comment; + post("oggwrite~: LOCATION = %s", x->x_bclocation); + } + else if(strstr(s->s_name, "COPYRIGHT")) + { + x->x_bccopyright = comment; + post("oggwrite~: COPYRIGHT = %s", x->x_bccopyright); + } + else if(strstr(s->s_name, "CONTACT")) + { + x->x_bccontact = comment; + post("oggwrite~: CONTACT = %s", x->x_bccontact); + } + else if(strstr(s->s_name, "DESCRIPTION")) + { + x->x_bcdescription = comment; + post("oggwrite~: DESCRIPTION = %s", x->x_bcdescription); + } + else if(strstr(s->s_name, "DATE")) + { + x->x_bcdate = comment; + post("oggwrite~: DATE=%s", x->x_bcdate); + } + else post("oggwrite~: no method for %s", s->s_name); + if(x->x_vorbis >=0) + { + oggwrite_vorbis_deinit(x); + oggwrite_vorbis_init(x); + } +} + + /* settings for variable bitrate encoding */ +static void oggwrite_vbr(t_oggwrite *x, t_floatarg fsr, t_floatarg fchannels, + t_floatarg fquality) +{ + x->x_vbr = 1; + x->x_samplerate = (t_int)fsr; + x->x_quality = fquality; + x->x_channels = (t_int)fchannels; + post("oggwrite~: %d channels @ %d Hz, quality %.2f", x->x_channels, x->x_samplerate, x->x_quality); + if(x->x_vorbis >=0) + { + oggwrite_vorbis_deinit(x); + oggwrite_vorbis_init(x); + } +} + + /* settings for bitrate-based vbr encoding */ +static void oggwrite_vorbis(t_oggwrite *x, t_floatarg fsr, t_floatarg fchannels, + t_floatarg fmax, t_floatarg fnom, t_floatarg fmin) +{ + x->x_vbr = 0; + x->x_samplerate = (t_int)fsr; + x->x_channels = (t_int)fchannels; + x->x_br_max = (t_int)fmax; + x->x_br_nom = (t_int)fnom; + x->x_br_min = (t_int)fmin; + post("oggwrite~: %d channels @ %d Hz, bitrates: max. %d / nom. %d / min. %d", + x->x_channels, x->x_samplerate, x->x_br_max, x->x_br_nom, x->x_br_min); + if(x->x_vorbis >=0) + { + oggwrite_vorbis_deinit(x); + oggwrite_vorbis_init(x); + } +} + + /* print settings to pd's console window */ +static void oggwrite_print(t_oggwrite *x) +{ + if(x->x_vbr == 1) + { + post("oggwrite~: Ogg Vorbis encoder: %d channels @ %d Hz, quality %.2f", x->x_channels, x->x_samplerate, x->x_quality); + } + else + { + post("oggwrite~: Ogg Vorbis encoder: %d channels @ %d Hz, bitrates: max. %d, nom. %d, min. %d", + x->x_channels, x->x_samplerate, x->x_br_max, x->x_br_nom, x->x_br_min); + } + post("oggwrite~: Ogg Vorbis comments:"); + post(" TITLE = %s", x->x_bcname); + post(" ARTIST = %s", x->x_bcartist); + post(" PERFORMER = %s", x->x_bcperformer); + post(" GENRE = %s", x->x_bcgenre); + post(" LOCATION = %s", x->x_bclocation); + post(" COPYRIGHT = %s", x->x_bccopyright); + post(" CONTACT = %s", x->x_bccontact); + post(" DESCRIPTION = %s", x->x_bcdescription); + post(" DATE = %s", x->x_bcdate); +} + + + /* clean up */ +static void oggwrite_free(t_oggwrite *x) +{ + if(x->x_vorbis >= 0) /* close encoder */ + { + oggwrite_vorbis_deinit(x); + } + if(x->x_fd >= 0) + { /* close file */ +#ifndef UNIX + _close(x->x_fd); +#else + close(x->x_fd); +#endif + outlet_float(x->x_obj.ob_outlet, 0); + } + freebytes(x->x_buffer, READ*sizeof(t_float)); +} + +static void *oggwrite_new(void) +{ + t_oggwrite *x = (t_oggwrite *)pd_new(oggwrite_class); + inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal")); + outlet_new(&x->x_obj, gensym("float")); + x->x_outpages = outlet_new(&x->x_obj, gensym("float")); + x->x_fd = -1; +#ifndef UNIX + x->x_file_open_mode = _O_CREAT|_O_WRONLY|_O_APPEND|_O_BINARY; +#else + x->x_file_open_mode = O_CREAT|O_WRONLY|O_APPEND|O_NONBLOCK; +#endif + x->x_vorbis = -1; + x->x_eos = 0; + x->x_vbr = 1; /* use the vbr setting by default */ + x->x_samplerate = sys_getsr(); /* no resampling supported, sorry */ + x->x_quality = 0.4; /* quality 0.4 gives roughly 128kbps VBR stream */ + x->x_channels = 2; /* stereo */ + x->x_br_max = 144; + x->x_br_nom = 128; + x->x_br_min = 96; + x->x_buffer = getbytes(READ*sizeof(t_float)); + if (!x->x_buffer) /* check buffer */ + { + error("out of memory!"); + } + x->x_bytesbuffered = 0; + x->x_pages = 0; + x->x_bcname = "ogg/vorbis stream"; + x->x_bcurl = "http://www.pure-data.org/"; + x->x_bcgenre = "experimental"; + x->x_bcdescription = "ogg/vorbis stream recorded with pure-data using oggwrite~"; + x->x_bcartist = "pure-data"; + x->x_bclocation = x->x_bcurl; + x->x_bccopyright = ""; + x->x_bcperformer = ""; + x->x_bccontact = ""; + x->x_bcdate = ""; + post(oggwrite_version); + return(x); +} + +void oggwrite_tilde_setup(void) +{ + oggwrite_class = class_new(gensym("oggwrite~"), (t_newmethod)oggwrite_new, (t_method)oggwrite_free, + sizeof(t_oggwrite), 0, 0); + CLASS_MAINSIGNALIN(oggwrite_class, t_oggwrite, x_f ); + class_sethelpsymbol(oggwrite_class, gensym("help-oggwrite~.pd")); + class_addmethod(oggwrite_class, (t_method)oggwrite_dsp, gensym("dsp"), 0); + class_addmethod(oggwrite_class, (t_method)oggwrite_open, gensym("open"), A_SYMBOL, 0); + class_addmethod(oggwrite_class, (t_method)oggwrite_start, gensym("start"), 0); + class_addmethod(oggwrite_class, (t_method)oggwrite_stop, gensym("stop"), 0); + class_addmethod(oggwrite_class, (t_method)oggwrite_append, gensym("append"), 0); + class_addmethod(oggwrite_class, (t_method)oggwrite_truncate, gensym("truncate"), 0); + class_addmethod(oggwrite_class, (t_method)oggwrite_vorbis, gensym("vorbis"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(oggwrite_class, (t_method)oggwrite_vbr, gensym("vbr"), A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(oggwrite_class, (t_method)oggwrite_print, gensym("print"), 0); + class_addanything(oggwrite_class, oggwrite_comment); +} diff --git a/oggwrite~/readme b/oggwrite~/readme index 4945d0d..b79840c 100644 --- a/oggwrite~/readme +++ b/oggwrite~/readme @@ -1,110 +1,110 @@ -oggwrite~ version 0.1b
-copyright (c) 2002 by Olaf Matthes
-
-oggwrite~ is an ogg/vorbis file writing external for pd (by Miller
-Puckette).
-
-
-To run oggwrite~ place the file oggwrite~.dll for win or oggwrite~.pd_linux
-in the directory of our patch or start pd with '-lib oggwrite~' flag.
-
-To compile oggwrite~ on Linux get the ogg/vorbice library from
-http://www.vorbis.com/.
-You have to modify the makefile to make it point to the place where the
-ogg/vorbis library is.
-
-
-This software is published under LGPL 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.
-
-*****************************************************************************
-
-oggwrite~ uses the ogg/vorbice library to encode audio data.
-The latest version of ogg/vorbis can be found at http://www.vorbice.com/
-
-Below is the original copyright information taken from the ogg/vorbis library:
-
-
-Copyright (c) 2001, Xiphophorus
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-- Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-
-- Neither the name of the Xiphophorus nor the names of its contributors
-may be used to endorse or promote products derived from this software
-without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*****************************************************************************
-
-Usage:
-
-Use message "vbr <samplerate> <channels> <quality>" to set the vorbis
-encoding parameters. Resampling is currently not supported, so 'samplerate'
-should be the one pd is running at. 'channels' specyfies the number of channels
-to stream. This can be set to 2 (default) or 1 which means mono stream taking
-the leftmost audio input only. 'quality' can be a value between 0.0 and 1.0
-giving the quality of the stream. 0.4 (default) results in a stream that's
-about 128kbps.
-
-Since Vorbis uses VBR encoding, bitrates vary depending on the type of audio
-signal to be encoded. A pure sine [osc~] results in the smalest stream, com-
-plex audio signals will increase this value significantly. To test the maximum
-bitrate that might occur for a quality setting use noise~ as signal input.
-
-Use message "vorbis <samplerate> <channels> <maximum bitrate> <nominal bit-
-rate> <minimal bitrate>" to set encoding quality on the basis of bitrates.
-When setting all three bitrate parameters to the same value one gets a
-constant bitrate stream. Values are in kbps!
-
-Message "open <filename>" opens an existing file. In case the file does not
-exist oggwrite~ will create it. Previously opened files will be closed. To
-determine how data should be written to the file choose "append" (default)
-or "truncate" (in case you want to overwrite data in your file).
-
-To set the comment tags in the ogg/vorbis header (which can be displayed by
-the receiving client) use message "<NAMEOFTAG> <comment>". Supported tags are:
-TITLE, ARTIST, GENRE, PERFORMER, LOCATION, COPYRIGHT, CONTACT, DESCRIPTION and
-DATE (which is automatically set to the date/time the broadcast started). To
-get spaces use '=' instead.
-
-Note that changing encoding parameters or header comments while oggwrite~ is
-recording to file might result in audible dropouts.
-
-
-Listening to it:
-
-To listen to ogg/vorbis encoded audio files many player need an extra plug-in.
-Have a look at http://www.vorbis.com/ to find the appropiate plug-in for your
-player.
-
-
-
-
-
-Latest version can be found at:
-http://www.akustische-kunst.de/puredata/
-
+oggwrite~ version 0.1b +copyright (c) 2002 by Olaf Matthes + +oggwrite~ is an ogg/vorbis file writing external for pd (by Miller +Puckette). + + +To run oggwrite~ place the file oggwrite~.dll for win or oggwrite~.pd_linux +in the directory of our patch or start pd with '-lib oggwrite~' flag. + +To compile oggwrite~ on Linux get the ogg/vorbice library from +http://www.vorbis.com/. +You have to modify the makefile to make it point to the place where the +ogg/vorbis library is. + + +This software is published under LGPL 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. + +***************************************************************************** + +oggwrite~ uses the ogg/vorbice library to encode audio data. +The latest version of ogg/vorbis can be found at http://www.vorbice.com/ + +Below is the original copyright information taken from the ogg/vorbis library: + + +Copyright (c) 2001, Xiphophorus + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of the Xiphophorus nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +***************************************************************************** + +Usage: + +Use message "vbr <samplerate> <channels> <quality>" to set the vorbis +encoding parameters. Resampling is currently not supported, so 'samplerate' +should be the one pd is running at. 'channels' specyfies the number of channels +to stream. This can be set to 2 (default) or 1 which means mono stream taking +the leftmost audio input only. 'quality' can be a value between 0.0 and 1.0 +giving the quality of the stream. 0.4 (default) results in a stream that's +about 128kbps. + +Since Vorbis uses VBR encoding, bitrates vary depending on the type of audio +signal to be encoded. A pure sine [osc~] results in the smalest stream, com- +plex audio signals will increase this value significantly. To test the maximum +bitrate that might occur for a quality setting use noise~ as signal input. + +Use message "vorbis <samplerate> <channels> <maximum bitrate> <nominal bit- +rate> <minimal bitrate>" to set encoding quality on the basis of bitrates. +When setting all three bitrate parameters to the same value one gets a +constant bitrate stream. Values are in kbps! + +Message "open <filename>" opens an existing file. In case the file does not +exist oggwrite~ will create it. Previously opened files will be closed. To +determine how data should be written to the file choose "append" (default) +or "truncate" (in case you want to overwrite data in your file). + +To set the comment tags in the ogg/vorbis header (which can be displayed by +the receiving client) use message "<NAMEOFTAG> <comment>". Supported tags are: +TITLE, ARTIST, GENRE, PERFORMER, LOCATION, COPYRIGHT, CONTACT, DESCRIPTION and +DATE (which is automatically set to the date/time the broadcast started). To +get spaces use '=' instead. + +Note that changing encoding parameters or header comments while oggwrite~ is +recording to file might result in audible dropouts. + + +Listening to it: + +To listen to ogg/vorbis encoded audio files many player need an extra plug-in. +Have a look at http://www.vorbis.com/ to find the appropiate plug-in for your +player. + + + + + +Latest version can be found at: +http://www.akustische-kunst.de/puredata/ + Please report any bugs to olaf.matthes@gmx.de!
\ No newline at end of file diff --git a/oggwrite~/vorbisenc.h b/oggwrite~/vorbisenc.h index 901c47a..1fc8913 100644 --- a/oggwrite~/vorbisenc.h +++ b/oggwrite~/vorbisenc.h @@ -1,93 +1,93 @@ -/********************************************************************
- * *
- * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
- * by the XIPHOPHORUS Company http://www.xiph.org/ *
- * *
- ********************************************************************
-
- function: vorbis encode-engine setup
- last mod: $Id: vorbisenc.h,v 1.1 2002-11-26 10:51:49 ggeiger Exp $
-
- ********************************************************************/
-
-#ifndef _OV_ENC_H_
-#define _OV_ENC_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif /* __cplusplus */
-
-#include "codec.h"
-
-extern int vorbis_encode_init(vorbis_info *vi,
- long channels,
- long rate,
-
- long max_bitrate,
- long nominal_bitrate,
- long min_bitrate);
-
-extern int vorbis_encode_setup_managed(vorbis_info *vi,
- long channels,
- long rate,
-
- long max_bitrate,
- long nominal_bitrate,
- long min_bitrate);
-
-extern int vorbis_encode_setup_vbr(vorbis_info *vi,
- long channels,
- long rate,
-
- float /* quality level from 0. (lo) to 1. (hi) */
- );
-
-extern int vorbis_encode_init_vbr(vorbis_info *vi,
- long channels,
- long rate,
-
- float base_quality /* quality level from 0. (lo) to 1. (hi) */
- );
-
-extern int vorbis_encode_setup_init(vorbis_info *vi);
-
-extern int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg);
-
-#define OV_ECTL_RATEMANAGE_GET 0x10
-
-#define OV_ECTL_RATEMANAGE_SET 0x11
-#define OV_ECTL_RATEMANAGE_AVG 0x12
-#define OV_ECTL_RATEMANAGE_HARD 0x13
-
-#define OV_ECTL_LOWPASS_GET 0x20
-#define OV_ECTL_LOWPASS_SET 0x21
-
-#define OV_ECTL_IBLOCK_GET 0x30
-#define OV_ECTL_IBLOCK_SET 0x31
-
-struct ovectl_ratemanage_arg {
- int management_active;
-
- long bitrate_hard_min;
- long bitrate_hard_max;
- double bitrate_hard_window;
-
- long bitrate_av_lo;
- long bitrate_av_hi;
- double bitrate_av_window;
- double bitrate_av_window_center;
-};
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif
-
-
+/******************************************************************** + * * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * + * by the XIPHOPHORUS Company http://www.xiph.org/ * + * * + ******************************************************************** + + function: vorbis encode-engine setup + last mod: $Id: vorbisenc.h,v 1.2 2003-04-23 10:36:25 xovo Exp $ + + ********************************************************************/ + +#ifndef _OV_ENC_H_ +#define _OV_ENC_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "codec.h" + +extern int vorbis_encode_init(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate); + +extern int vorbis_encode_setup_managed(vorbis_info *vi, + long channels, + long rate, + + long max_bitrate, + long nominal_bitrate, + long min_bitrate); + +extern int vorbis_encode_setup_vbr(vorbis_info *vi, + long channels, + long rate, + + float /* quality level from 0. (lo) to 1. (hi) */ + ); + +extern int vorbis_encode_init_vbr(vorbis_info *vi, + long channels, + long rate, + + float base_quality /* quality level from 0. (lo) to 1. (hi) */ + ); + +extern int vorbis_encode_setup_init(vorbis_info *vi); + +extern int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg); + +#define OV_ECTL_RATEMANAGE_GET 0x10 + +#define OV_ECTL_RATEMANAGE_SET 0x11 +#define OV_ECTL_RATEMANAGE_AVG 0x12 +#define OV_ECTL_RATEMANAGE_HARD 0x13 + +#define OV_ECTL_LOWPASS_GET 0x20 +#define OV_ECTL_LOWPASS_SET 0x21 + +#define OV_ECTL_IBLOCK_GET 0x30 +#define OV_ECTL_IBLOCK_SET 0x31 + +struct ovectl_ratemanage_arg { + int management_active; + + long bitrate_hard_min; + long bitrate_hard_max; + double bitrate_hard_window; + + long bitrate_av_lo; + long bitrate_av_hi; + double bitrate_av_window; + double bitrate_av_window_center; +}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + + |