1 /* libSoX Ogg Vorbis sound format handler
2 * Copyright 2001, Stan Seibert <indigo@aztec.asu.edu>
4 * Portions from oggenc, (c) Michael Smith <msmith@labyrinth.net.au>,
5 * ogg123, (c) Kenneth Arnold <kcarnold@yahoo.com>, and
6 * libvorbisfile (c) Xiphophorus Company
8 * May 9, 2001 - Stan Seibert (indigo@aztec.asu.edu)
9 * Ogg Vorbis handler initially written.
11 * July 5, 1991 - Skeleton file
12 * Copyright 1991 Lance Norskog And Sundry Contributors
13 * This source code is freely redistributable and may be used for
14 * any purpose. This copyright notice must be maintained.
15 * Lance Norskog And Sundry Contributors are not responsible for
16 * the consequences of using this software.
26 #include <vorbis/codec.h>
27 #include <vorbis/vorbisfile.h>
28 #include <vorbis/vorbisenc.h>
30 #define DEF_BUF_LEN 4096
36 #define HEADER_ERROR 0
39 /* Private data for Ogg Vorbis file */
56 size_t end
; /* Unsent data samples in buf[start] through buf[end-1] */
60 vorbis_enc_t
*vorbis_enc_data
;
63 /******** Callback functions used in ov_open_callbacks ************/
65 static size_t callback_read(void* ptr
, size_t size
, size_t nmemb
, void* ft_data
)
67 sox_format_t
* ft
= (sox_format_t
*)ft_data
;
68 size_t ret
= lsx_readbuf(ft
, ptr
, size
* nmemb
);
72 static int callback_seek(void* ft_data
, ogg_int64_t off
, int whence
)
74 sox_format_t
* ft
= (sox_format_t
*)ft_data
;
75 int ret
= ft
->seekable
? lsx_seeki(ft
, (off_t
)off
, whence
) : -1;
82 static int callback_close(void* ft_data UNUSED
)
84 /* Do nothing so sox can close the file for us */
88 static long callback_tell(void* ft_data
)
90 sox_format_t
* ft
= (sox_format_t
*)ft_data
;
94 /********************* End callbacks *****************************/
98 * Do anything required before you start reading samples.
100 * Find out sampling rate,
101 * size and encoding of samples,
104 static int startread(sox_format_t
* ft
)
106 priv_t
* vb
= (priv_t
*) ft
->priv
;
111 ov_callbacks callbacks
= {
118 /* Allocate space for decoding structure */
119 vb
->vf
= lsx_malloc(sizeof(OggVorbis_File
));
121 /* Init the decoder */
122 if (ov_open_callbacks(ft
, vb
->vf
, NULL
, (size_t) 0, callbacks
) < 0) {
123 lsx_fail_errno(ft
, SOX_EHDR
, "Input not an Ogg Vorbis audio stream");
127 /* Get info about the Ogg Vorbis stream */
128 vi
= ov_info(vb
->vf
, -1);
129 vc
= ov_comment(vb
->vf
, -1);
131 /* Record audio info */
132 ft
->signal
.rate
= vi
->rate
;
133 ft
->encoding
.encoding
= SOX_ENCODING_VORBIS
;
134 ft
->signal
.channels
= vi
->channels
;
136 /* ov_pcm_total doesn't work on non-seekable files so
137 * skip that step in that case. Also, it reports
138 * "frame"-ish results so we must * channels.
141 ft
->signal
.length
= ov_pcm_total(vb
->vf
, -1) * ft
->signal
.channels
;
143 /* Record comments */
144 for (i
= 0; i
< vc
->comments
; i
++)
145 sox_append_comment(&ft
->oob
.comments
, vc
->user_comments
[i
]);
148 vb
->buf_len
= DEF_BUF_LEN
;
149 vb
->buf_len
-= vb
->buf_len
% (vi
->channels
*2); /* 2 bytes per sample */
150 vb
->buf
= lsx_calloc(vb
->buf_len
, sizeof(char));
151 vb
->start
= vb
->end
= 0;
153 /* Fill in other info */
155 vb
->current_section
= -1;
157 return (SOX_SUCCESS
);
161 /* Refill the buffer with samples. Returns BUF_EOF if the end of the
162 * vorbis data was reached while the buffer was being filled,
163 * BUF_ERROR is something bad happens, and BUF_DATA otherwise */
164 static int refill_buffer(priv_t
* vb
)
168 if (vb
->start
== vb
->end
) /* Samples all played */
169 vb
->start
= vb
->end
= 0;
171 while (vb
->end
< vb
->buf_len
) {
172 num_read
= ov_read(vb
->vf
, vb
->buf
+ vb
->end
,
173 (int) (vb
->buf_len
- vb
->end
), 0, 2, 1, &vb
->current_section
);
176 else if (num_read
== OV_HOLE
)
177 lsx_warn("Warning: hole in stream; probably harmless");
178 else if (num_read
< 0)
188 * Read up to len samples from file.
189 * Convert to signed longs.
191 * Return number of samples read.
194 static size_t read_samples(sox_format_t
* ft
, sox_sample_t
* buf
, size_t len
)
196 priv_t
* vb
= (priv_t
*) ft
->priv
;
202 for (i
= 0; i
< len
; i
++) {
203 if (vb
->start
== vb
->end
) {
206 ret
= refill_buffer(vb
);
207 if (ret
== BUF_EOF
|| ret
== BUF_ERROR
) {
214 l
= (vb
->buf
[vb
->start
+ 1] << 24)
215 | (0xffffff & (vb
->buf
[vb
->start
] << 16));
223 * Do anything required when you stop reading samples.
224 * Don't close input file!
226 static int stopread(sox_format_t
* ft
)
228 priv_t
* vb
= (priv_t
*) ft
->priv
;
233 return (SOX_SUCCESS
);
236 /* Write a page of ogg data to a file. Taken directly from encode.c in
237 * oggenc. Returns the number of bytes written. */
238 static int oe_write_page(ogg_page
* page
, sox_format_t
* ft
)
242 written
= lsx_writebuf(ft
, page
->header
, (size_t) page
->header_len
);
243 written
+= lsx_writebuf(ft
, page
->body
, (size_t) page
->body_len
);
248 /* Write out the header packets. Derived mostly from encode.c in oggenc.
249 * Returns HEADER_OK if the header can be written, HEADER_ERROR otherwise. */
250 static int write_vorbis_header(sox_format_t
* ft
, vorbis_enc_t
* ve
)
252 ogg_packet header_main
;
253 ogg_packet header_comments
;
254 ogg_packet header_codebooks
;
256 int i
, ret
= HEADER_OK
;
258 memset(&vc
, 0, sizeof(vc
));
259 vc
.comments
= sox_num_comments(ft
->oob
.comments
);
260 if (vc
.comments
) { /* Make the comment structure */
261 vc
.comment_lengths
= lsx_calloc((size_t)vc
.comments
, sizeof(*vc
.comment_lengths
));
262 vc
.user_comments
= lsx_calloc((size_t)vc
.comments
, sizeof(*vc
.user_comments
));
263 for (i
= 0; i
< vc
.comments
; ++i
) {
264 static const char prepend
[] = "Comment=";
265 char * text
= lsx_calloc(strlen(prepend
) + strlen(ft
->oob
.comments
[i
]) + 1, sizeof(*text
));
266 /* Prepend `Comment=' if no field-name already in the comment */
267 if (!strchr(ft
->oob
.comments
[i
], '='))
268 strcpy(text
, prepend
);
269 vc
.user_comments
[i
] = strcat(text
, ft
->oob
.comments
[i
]);
270 vc
.comment_lengths
[i
] = strlen(text
);
273 if (vorbis_analysis_headerout( /* Build the packets */
274 &ve
->vd
, &vc
, &header_main
, &header_comments
, &header_codebooks
) < 0) {
279 ogg_stream_packetin(&ve
->os
, &header_main
); /* And stream them out */
280 ogg_stream_packetin(&ve
->os
, &header_comments
);
281 ogg_stream_packetin(&ve
->os
, &header_codebooks
);
283 while (ogg_stream_flush(&ve
->os
, &ve
->og
) && ret
== HEADER_OK
)
284 if (!oe_write_page(&ve
->og
, ft
))
287 for (i
= 0; i
< vc
.comments
; ++i
)
288 free(vc
.user_comments
[i
]);
289 free(vc
.user_comments
);
290 free(vc
.comment_lengths
);
294 static int startwrite(sox_format_t
* ft
)
296 priv_t
* vb
= (priv_t
*) ft
->priv
;
299 double quality
= 3; /* Default compression quality gives ~112kbps */
301 ft
->encoding
.encoding
= SOX_ENCODING_VORBIS
;
303 /* Allocate memory for all of the structures */
304 ve
= vb
->vorbis_enc_data
= lsx_malloc(sizeof(vorbis_enc_t
));
306 vorbis_info_init(&ve
->vi
);
309 rate
= ft
->signal
.rate
;
311 lsx_fail_errno(ft
, SOX_EHDR
,
312 "Error setting-up Ogg Vorbis encoder; check sample-rate & # of channels");
314 /* Use encoding to average bit rate of VBR as specified by the -C option */
315 if (ft
->encoding
.compression
!= HUGE_VAL
) {
316 if (ft
->encoding
.compression
< -1 || ft
->encoding
.compression
> 10) {
317 lsx_fail_errno(ft
, SOX_EINVAL
,
318 "Vorbis compression quality nust be between -1 and 10");
321 quality
= ft
->encoding
.compression
;
324 if (vorbis_encode_init_vbr(&ve
->vi
, ft
->signal
.channels
, ft
->signal
.rate
+ .5, quality
/ 10))
326 lsx_fail_errno(ft
, SOX_EFMT
, "libVorbis cannot encode this sample-rate or # of channels");
330 vorbis_analysis_init(&ve
->vd
, &ve
->vi
);
331 vorbis_block_init(&ve
->vd
, &ve
->vb
);
333 ogg_stream_init(&ve
->os
, INT_MAX
& (int)RANQD1
); /* Random serial number */
335 if (write_vorbis_header(ft
, ve
) == HEADER_ERROR
) {
336 lsx_fail_errno(ft
, SOX_EHDR
,
337 "Error writing header for Ogg Vorbis audio stream");
341 return (SOX_SUCCESS
);
344 static size_t write_samples(sox_format_t
* ft
, const sox_sample_t
* buf
,
347 priv_t
* vb
= (priv_t
*) ft
->priv
;
348 vorbis_enc_t
*ve
= vb
->vorbis_enc_data
;
349 size_t samples
= len
/ ft
->signal
.channels
;
350 float **buffer
= vorbis_analysis_buffer(&ve
->vd
, (int) samples
);
355 /* Copy samples into vorbis buffer */
356 for (i
= 0; i
< samples
; i
++)
357 for (j
= 0; j
< ft
->signal
.channels
; j
++)
358 buffer
[j
][i
] = buf
[i
* ft
->signal
.channels
+ j
]
359 / ((float) SOX_SAMPLE_MAX
);
361 vorbis_analysis_wrote(&ve
->vd
, (int) samples
);
363 while (vorbis_analysis_blockout(&ve
->vd
, &ve
->vb
) == 1) {
364 /* Do the main analysis, creating a packet */
365 vorbis_analysis(&ve
->vb
, &ve
->op
);
366 vorbis_bitrate_addblock(&ve
->vb
);
368 /* Add packet to bitstream */
369 while (vorbis_bitrate_flushpacket(&ve
->vd
, &ve
->op
)) {
370 ogg_stream_packetin(&ve
->os
, &ve
->op
);
372 /* If we've gone over a page boundary, we can do actual
373 * output, so do so (for however many pages are available)
377 int result
= ogg_stream_pageout(&ve
->os
, &ve
->og
);
382 ret
= oe_write_page(&ve
->og
, ft
);
386 if (ogg_page_eos(&ve
->og
))
395 static int stopwrite(sox_format_t
* ft
)
397 priv_t
* vb
= (priv_t
*) ft
->priv
;
398 vorbis_enc_t
*ve
= vb
->vorbis_enc_data
;
400 /* Close out the remaining data */
401 write_samples(ft
, NULL
, (size_t) 0);
403 ogg_stream_clear(&ve
->os
);
404 vorbis_block_clear(&ve
->vb
);
405 vorbis_dsp_clear(&ve
->vd
);
406 vorbis_info_clear(&ve
->vi
);
408 return (SOX_SUCCESS
);
411 static int seek(sox_format_t
* ft
, uint64_t offset
)
413 priv_t
* vb
= (priv_t
*) ft
->priv
;
415 return ov_pcm_seek(vb
->vf
, (ogg_int64_t
)(offset
/ ft
->signal
.channels
))? SOX_EOF
:SOX_SUCCESS
;
418 LSX_FORMAT_HANDLER(vorbis
)
420 static const char *names
[] = {"vorbis", "ogg", NULL
};
421 static const unsigned encodings
[] = {SOX_ENCODING_VORBIS
, 0, 0};
422 static sox_format_handler_t handler
= {SOX_LIB_VERSION_CODE
,
423 "Xiph.org's ogg-vorbis lossy compression", names
, 0,
424 startread
, read_samples
, stopread
,
425 startwrite
, write_samples
, stopwrite
,
426 seek
, encodings
, NULL
, sizeof(priv_t
)