1
/********************************************************************
3
Derived from work with the following disclamer below:
6
Copyright (c) 2002-2004 Xiph.org Foundation
8
Redistribution and use in source and binary forms, with or without
9
modification, are permitted provided that the following conditions
12
- Redistributions of source code must retain the above copyright
13
notice, this list of conditions and the following disclaimer.
15
- Redistributions in binary form must reproduce the above copyright
16
notice, this list of conditions and the following disclaimer in the
17
documentation and/or other materials provided with the distribution.
19
- Neither the name of the Xiph.org Foundation nor the names of its
20
contributors may be used to endorse or promote products derived from
21
this software without specific prior written permission.
23
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
27
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
********************************************************************/
38
/* Note that this is POSIX, not ANSI, code */
46
#include <vorbis/vorbisenc.h>
48
#ifdef _WIN32 /* We need the following two to set stdout to binary */
53
#if defined(__MACOS__) && defined(__MWERKS__)
54
#include <console.h> /* CodeWarrior's Mac "command-line" support */
56
#include <xmmsclient/xmmsclient.h>
59
printf ("Error: %s\n", msg); \
63
signed char readbuffer[READ*4]; /* out of the data segment, not the stack */
66
xmmsc_connection_t *x_connection;
79
xmmsc_visualization_shutdown (x_connection, x_vis);
81
xmmsc_unref (x_connection);
88
char *path = getenv ("XMMS_PATH");
91
x_connection = xmmsc_init ("xmms2-ripper");
93
if (!x_connection || !xmmsc_connect (x_connection, path)){
94
printf ("%s\n", xmmsc_get_last_error (x_connection));
95
x_exit ("couldn't connect to xmms2d!");
98
res = xmmsc_visualization_init (x_connection);
99
xmmsc_result_wait (res);
100
if (xmmsc_result_iserror (res)) {
101
puts (xmmsc_result_get_error (res));
104
x_vis = xmmsc_visualization_init_handle (res);
106
cfg = xmmsv_build_dict (XMMSV_DICT_ENTRY_STR ("type", "pcm"),
107
XMMSV_DICT_ENTRY_STR ("stereo", "1"),
108
XMMSV_DICT_ENTRY_STR ("pcm.hardwire", "1"),
111
res = xmmsc_visualization_properties_set (x_connection, x_vis, cfg);
112
xmmsc_result_wait (res);
113
if (xmmsc_result_iserror (res)) {
114
x_exit (xmmsc_result_get_error (res));
116
xmmsc_result_unref (res);
118
while (!xmmsc_visualization_started (x_connection, x_vis)) {
119
res = xmmsc_visualization_start (x_connection, x_vis);
120
if (xmmsc_visualization_errored (x_connection, x_vis)) {
121
printf ("Couldn't start visualization transfer: %s\n",
122
xmmsc_get_last_error (x_connection));
126
xmmsc_result_wait (res);
127
xmmsc_visualization_start_handle (x_connection, res);
128
xmmsc_result_unref (res);
137
ogg_stream_state os; /* take physical pages, weld into a logical
139
ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */
140
ogg_packet op; /* one raw packet of data for decode */
142
vorbis_info vi; /* struct that stores all the static vorbis bitstream
144
vorbis_comment vc; /* struct that stores all the user comments */
146
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
147
vorbis_block vb; /* local working space for packet->PCM decode */
149
struct sigaction siga;
154
#if defined(macintosh) && defined(__MWERKS__)
157
argc = ccommand (&argv); /* get a "command line" from the Mac user */
160
#ifdef _WIN32 /* We need to set stdout to binary mode. Damn windows. */
161
/* if we were writing a file, it would also need to in
162
binary mode, eg, fopen("file.wav","wb"); */
163
_setmode (_fileno (stdout), _O_BINARY);
166
siga.sa_handler = quit;
167
sigemptyset (&siga.sa_mask);
168
siga.sa_flags = SA_RESTART;
170
/********** Init xmms2 **************/
173
/********** Encode setup ************/
175
vorbis_info_init (&vi);
177
/* TODO: command line quality setting */
178
ret = vorbis_encode_init_vbr (&vi, 2, 44100, 0.4);
180
x_exit ("Setting up vorbis format failed!");
184
vorbis_comment_init (&vc);
185
vorbis_comment_add_tag (&vc, "ENCODER", "xmms2");
187
/* set up the analysis state and auxiliary encoding storage */
188
vorbis_analysis_init (&vd, &vi);
189
vorbis_block_init (&vd, &vb);
191
/* set up our packet->stream encoder */
192
/* pick a random serial number; that way we can more likely build
193
chained streams just by concatenation */
195
ogg_stream_init (&os, rand ());
197
/* Vorbis streams begin with three headers; the initial header (with
198
most of the codec setup parameters) which is mandated by the Ogg
199
bitstream spec. The second header holds any comment fields. The
200
third header holds the bitstream codebook. We merely need to
201
make the headers, then pass them to libvorbis one at a time;
202
libvorbis handles the additional Ogg bitstream constraints */
205
ogg_packet header_comm;
206
ogg_packet header_code;
208
vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code);
209
ogg_stream_packetin (&os, &header); /* automatically placed in its own
211
ogg_stream_packetin (&os, &header_comm);
212
ogg_stream_packetin (&os, &header_code);
214
/* This ensures the actual
215
* audio data will start on a new page, as per spec
218
int result = ogg_stream_flush (&os, &og);
222
fwrite (og.header, 1, og.header_len, stdout);
223
fwrite (og.body, 1, og.body_len, stdout);
227
sigaction(SIGINT, &siga, (struct sigaction*)NULL);
229
fprintf (stderr, "Ready to encode... ");
233
long bytes = xmmsc_visualization_chunk_get (x_connection, x_vis, (short*)readbuffer, -1, 1000) * sizeof(short);
237
if (bytes < 0 || intr) {
238
/* Tell the library we're at end of stream so that it can handle
239
the last frame and mark end of stream in the output properly */
240
vorbis_analysis_wrote (&vd, 0);
244
fprintf (stderr, "\rEncoding: ");
248
fprintf (stderr, "\b%c", stat);
250
case '-': stat = '\\'; break;
251
case '\\': stat = '|'; break;
252
case '|': stat = '/'; break;
253
default: stat = '-'; break;
258
/* expose the buffer to submit data */
259
float **buffer = vorbis_analysis_buffer (&vd, READ);
261
/* uninterleave samples */
262
for (i = 0; i < bytes/4; i++) {
263
buffer[0][i] = ((readbuffer[i*4+1] << 8) |
264
(0x00ff & (int)readbuffer[i*4]))
266
buffer[1][i] = ((readbuffer[i*4+3] << 8) |
267
(0x00ff & (int)readbuffer[i*4+2]))
271
/* tell the library how much we actually submitted */
272
vorbis_analysis_wrote (&vd, i);
275
/* vorbis does some data preanalysis, then divvies up blocks for
276
more involved (potentially parallel) processing. Get a single
277
block for encoding now */
278
while (vorbis_analysis_blockout (&vd, &vb) == 1) {
280
/* analysis, assume we want to use bitrate management */
281
vorbis_analysis (&vb, NULL);
282
vorbis_bitrate_addblock (&vb);
284
while (vorbis_bitrate_flushpacket (&vd, &op)) {
286
/* weld the packet into the bitstream */
287
ogg_stream_packetin (&os, &op);
289
/* write out pages (if any) */
290
while (!ogg_page_eos (&og)) {
291
int result = ogg_stream_pageout (&os, &og);
295
fwrite (og.header, 1, og.header_len, stdout);
296
fwrite (og.body, 1, og.body_len, stdout);
302
/* clean up and exit. vorbis_info_clear () must be called last */
304
ogg_stream_clear (&os);
305
vorbis_block_clear (&vb);
306
vorbis_dsp_clear (&vd);
307
vorbis_comment_clear (&vc);
308
vorbis_info_clear (&vi);
310
/* ogg_page and ogg_packet structs always point to storage in
311
libvorbis. They're never freed or manipulated directly */
313
fprintf (stderr, "\rDone. \n");