1 /*
2 ** Copyright (C) 2002-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** Copyright (C) 2002-2005 Michael Smith <msmith@xiph.org>
4 ** Copyright (C) 2007 John ffitch
5 **
6 ** This program is free software ; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published by
8 ** the Free Software Foundation ; either version 2.1 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY ; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU Lesser General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program ; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 /*
22 ** Much of this code is based on the examples in libvorbis from the
23 ** XIPHOPHORUS Company http://www.xiph.org/ which has a BSD-style Licence
24 ** Copyright (c) 2002, Xiph.org Foundation
25 **
26 ** Redistribution and use in source and binary forms, with or without
27 ** modification, are permitted provided that the following conditions
28 ** are met:
29 **
30 ** - Redistributions of source code must retain the above copyright
31 ** notice, this list of conditions and the following disclaimer.
32 **
33 ** - Redistributions in binary form must reproduce the above copyright
34 ** notice, this list of conditions and the following disclaimer in the
35 ** documentation and/or other materials provided with the distribution.
36 **
37 ** - Neither the name of the Xiph.org Foundation nor the names of its
38 ** contributors may be used to endorse or promote products derived from
39 ** this software without specific prior written permission.
40 **
41 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
42 ** ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
43 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
44 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
45 ** OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE,
48 ** DATA, OR PROFITS ; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
51 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 */
53
54 #include "sfconfig.h"
55
56 #include <stdio.h>
57 #include <fcntl.h>
58 #include <string.h>
59 #include <ctype.h>
60 #include <time.h>
61 #include <math.h>
62
63 #if HAVE_UNISTD_H
64 #include <unistd.h>
65 #else
66 #include "sf_unistd.h"
67 #endif
68
69 #include "sndfile.h"
70 #include "sfendian.h"
71 #include "common.h"
72
73 #if HAVE_EXTERNAL_XIPH_LIBS
74
75 #include <ogg/ogg.h>
76 #include <vorbis/codec.h>
77 #include <vorbis/vorbisenc.h>
78
79 #include "ogg.h"
80
81 typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ;
82
83 static int vorbis_read_header (SF_PRIVATE *psf) ;
84 static int vorbis_write_header (SF_PRIVATE *psf, int calc_length) ;
85 static int vorbis_close (SF_PRIVATE *psf) ;
86 static int vorbis_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
87 static int vorbis_byterate (SF_PRIVATE *psf) ;
88 static sf_count_t vorbis_calculate_page_duration (SF_PRIVATE *psf) ;
89 static sf_count_t vorbis_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
90 static sf_count_t vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
91 static sf_count_t vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
92 static sf_count_t vorbis_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
93 static sf_count_t vorbis_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
94 static sf_count_t vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
95 static sf_count_t vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
96 static sf_count_t vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
97 static sf_count_t vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
98 static sf_count_t vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn) ;
99 static int vorbis_rnull (SF_PRIVATE *psf, int samples, void *vptr, int off , int channels, float **pcm) ;
100
101 typedef struct
102 { int id ;
103 const char *name ;
104 } STR_PAIRS ;
105
106
107 /* See https://xiph.org/vorbis/doc/v-comment.html */
108 static STR_PAIRS vorbis_metatypes [] =
109 { { SF_STR_TITLE, "Title" },
110 { SF_STR_COPYRIGHT, "Copyright" },
111 { SF_STR_SOFTWARE, "Software" },
112 { SF_STR_ARTIST, "Artist" },
113 { SF_STR_COMMENT, "Comment" },
114 { SF_STR_DATE, "Date" },
115 { SF_STR_ALBUM, "Album" },
116 { SF_STR_LICENSE, "License" },
117 { SF_STR_TRACKNUMBER, "Tracknumber" },
118 { SF_STR_GENRE, "Genre" },
119 } ;
120
121 typedef struct
122 { /* Count current location */
123 sf_count_t loc ;
124 /* Struct that stores all the static vorbis bitstream settings */
125 vorbis_info vinfo ;
126 /* Struct that stores all the bitstream user comments */
127 vorbis_comment vcomment ;
128 /* Ventral working state for the packet->PCM decoder */
129 vorbis_dsp_state vdsp ;
130 /* Local working space for packet->PCM decode */
131 vorbis_block vblock ;
132
133 /* Encoding quality in range [0.0, 1.0]. */
134 double quality ;
135
136 /* Current granule position. */
137 uint64_t pcm_current ;
138 /* Offset of the first samples' granule position. */
139 uint64_t pcm_start ;
140 /* Last valid samples' granule position. */
141 uint64_t pcm_end ;
142 /* File offset of the start of the last page. */
143 sf_count_t last_page ;
144 } VORBIS_PRIVATE ;
145
146 static int
vorbis_read_header(SF_PRIVATE * psf)147 vorbis_read_header (SF_PRIVATE *psf)
148 { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
149 VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
150 sf_count_t duration ;
151 int printed_metadata_msg = 0 ;
152 int i, k, nn ;
153
154 /*
155 ** The first page of the Ogg stream we are told to try and open as Vorbis
156 ** has already been loaded into odata->ostream by ogg_open().
157 **
158 ** Extract the initial header from the first page and verify that the
159 ** Ogg bitstream is in fact Vorbis data.
160 */
161
162 vorbis_info_init (&vdata->vinfo) ;
163 vorbis_comment_init (&vdata->vcomment) ;
164
165 if (!odata->opacket.b_o_s)
166 { psf_log_printf (psf, "Vorbis: First packet does not have a beginning-of-stream bit.\n") ;
167 return SFE_MALFORMED_FILE ;
168 }
169
170 if (ogg_stream_packetpeek (&odata->ostream, NULL))
171 { psf_log_printf (psf, "Vorbis: First page contains extraneous packets!\n") ;
172 return SFE_MALFORMED_FILE ;
173 }
174
175 if (vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) < 0)
176 { /* Error case ; not a vorbis header. */
177 psf_log_printf (psf, "Found Vorbis in stream header, but vorbis_synthesis_headerin failed.\n") ;
178 return SFE_MALFORMED_FILE ;
179 } ;
180
181 /*
182 ** At this point, we're sure we're Vorbis. We've set up the logical (Ogg)
183 ** bitstream decoder. Get the comment and codebook headers and set up the
184 ** Vorbis decoder.
185 **
186 ** The next two packets in order are the comment and codebook headers.
187 ** They're likely large and may span multiple pages. Thus we reead
188 ** and submit data until we get our two pacakets, watching that no
189 ** pages are missing. If a page is missing, error out ; losing a
190 ** header page is the only place where missing data is fatal.
191 */
192
193 i = 0 ; /* Count of number of packets read */
194 while (i < 2)
195 { nn = ogg_stream_packetout (&odata->ostream, &odata->opacket) ;
196
197 if (nn == 0)
198 { nn = ogg_stream_next_page (psf, odata) ;
199 if (nn == 0)
200 { psf_log_printf (psf, "End of file before finding all Vorbis headers!\n") ;
201 return SFE_MALFORMED_FILE ;
202 } ;
203 if (nn == -1)
204 { psf_log_printf (psf, "Error reading file while finding Vorbis headers!\n") ;
205 return psf->error ;
206 } ;
207 continue ;
208 }
209
210 if (nn < 0)
211 { /* A hole while reading headers. This could be bad. */
212 psf_log_printf (psf, "Corrupt secondary header. Exiting.\n") ;
213 return SFE_MALFORMED_FILE ;
214 } ;
215
216 vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) ;
217 i++ ;
218 } ;
219
220 /* Check for extraneous packets in the last headers page. */
221 while (ogg_stream_packetout (&odata->ostream, &odata->opacket) == 1)
222 { i++ ;
223 }
224 if (i > 2)
225 psf_log_printf (psf, "Vorbis: stream has extraneous header packets.\n") ;
226
227 psf_log_printf (psf, "Bitstream is %d channel, %D Hz\n", vdata->vinfo.channels, vdata->vinfo.rate) ;
228 psf_log_printf (psf, "Encoded by : %s\n", vdata->vcomment.vendor) ;
229
230 /* Save the offset of the first payload page */
231 psf->dataoffset = ogg_sync_ftell (psf) ;
232
233 /*
234 ** Caculate the granule position offset. The first page with a payload
235 ** packet shouldn't end in a continued packet. The difference between the
236 ** page's granule position and the sum of frames on the page tells us the
237 ** granule position offset.
238 ** See https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-132000A.2
239 */
240 ogg_stream_unpack_page (psf, odata) ;
241 vdata->pcm_start = odata->pkt [odata->pkt_len - 1].granulepos ;
242 duration = vorbis_calculate_page_duration (psf) ;
243
244 if (duration < (sf_count_t) vdata->pcm_start)
245 vdata->pcm_start -= duration ;
246 else
247 vdata->pcm_start = 0 ;
248
249 /*
250 ** Find the end of the stream, save it. Only works if the file is seekable.
251 */
252 vdata->loc = vdata->pcm_start ;
253 vdata->pcm_end = (uint64_t) -1 ;
254 psf->datalength = psf->filelength ;
255 if (!psf->is_pipe)
256 { sf_count_t last_page ;
257 sf_count_t saved_offset ;
258
259 saved_offset = ogg_sync_ftell (psf) ;
260 last_page = ogg_sync_last_page_before (psf, odata, &vdata->pcm_end, psf->filelength, odata->ostream.serialno) ;
261 if (last_page > 0)
262 { if (!ogg_page_eos (&odata->opage))
263 psf_log_printf (psf, "Ogg: Last page lacks an end-of-stream bit.\n") ;
264 psf->datalength = last_page + odata->opage.header_len + odata->opage.body_len - psf->dataoffset ;
265 if (psf->datalength + psf->dataoffset < psf->filelength)
266 psf_log_printf (psf, "Ogg: Junk after the last page.\n") ;
267 vdata->last_page = last_page ;
268 } ;
269
270 ogg_sync_fseek (psf, saved_offset, SEEK_SET) ;
271 }
272
273 psf_log_printf (psf, "PCM offset : %d\n", vdata->pcm_start) ;
274 if (vdata->pcm_end != (uint64_t) -1)
275 psf_log_printf (psf, "PCM end : %d\n", vdata->pcm_end) ;
276 else
277 psf_log_printf (psf, "PCM end : unknown\n") ;
278
279 /* Throw the comments plus a few lines about the bitstream we're decoding. */
280 for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
281 { char *dd ;
282
283 dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ;
284 if (dd == NULL)
285 continue ;
286
287 if (printed_metadata_msg == 0)
288 { psf_log_printf (psf, "Metadata :\n") ;
289 printed_metadata_msg = 1 ;
290 } ;
291
292 psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
293 psf_log_printf (psf, " %-10s : %s\n", vorbis_metatypes [k].name, dd) ;
294 } ;
295 psf_log_printf (psf, "End\n") ;
296
297 psf->sf.samplerate = vdata->vinfo.rate ;
298 psf->sf.channels = vdata->vinfo.channels ;
299 psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
300 psf->sf.frames = (vdata->pcm_end != (uint64_t) -1) ? vdata->pcm_end - vdata->pcm_start : SF_COUNT_MAX ;
301
302 /* OK, got and parsed all three headers. Initialize the Vorbis
303 ** packet->PCM decoder.
304 ** Central decode state. */
305 vorbis_synthesis_init (&vdata->vdsp, &vdata->vinfo) ;
306
307 /* Local state for most of the decode so multiple block decodes can
308 ** proceed in parallel. We could init multiple vorbis_block structures
309 ** for vd here. */
310 vorbis_block_init (&vdata->vdsp, &vdata->vblock) ;
311
312 return 0 ;
313 } /* vorbis_read_header */
314
315 static int
vorbis_write_header(SF_PRIVATE * psf,int UNUSED (calc_length))316 vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
317 {
318 OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
319 VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
320 int k, ret ;
321
322 vorbis_info_init (&vdata->vinfo) ;
323
324 /* The style of encoding should be selectable here, VBR quality mode. */
325 ret = vorbis_encode_init_vbr (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, vdata->quality) ;
326
327 #if 0
328 ret = vorbis_encode_init (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) ; /* average bitrate mode */
329 ret = ( vorbis_encode_setup_managed (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1)
330 || vorbis_encode_ctl (&vdata->vinfo, OV_ECTL_RATEMANAGE_AVG, NULL)
331 || vorbis_encode_setup_init (&vdata->vinfo)
332 ) ;
333 #endif
334 if (ret)
335 return SFE_BAD_OPEN_FORMAT ;
336
337 vdata->loc = 0 ;
338
339 /* add a comment */
340 vorbis_comment_init (&vdata->vcomment) ;
341
342 vorbis_comment_add_tag (&vdata->vcomment, "ENCODER", "libsndfile") ;
343 for (k = 0 ; k < SF_MAX_STRINGS ; k++)
344 { const char * name ;
345
346 if (psf->strings.data [k].type == 0)
347 break ;
348
349 switch (psf->strings.data [k].type)
350 { case SF_STR_TITLE : name = "TITLE" ; break ;
351 case SF_STR_COPYRIGHT : name = "COPYRIGHT" ; break ;
352 case SF_STR_SOFTWARE : name = "SOFTWARE" ; break ;
353 case SF_STR_ARTIST : name = "ARTIST" ; break ;
354 case SF_STR_COMMENT : name = "COMMENT" ; break ;
355 case SF_STR_DATE : name = "DATE" ; break ;
356 case SF_STR_ALBUM : name = "ALBUM" ; break ;
357 case SF_STR_LICENSE : name = "LICENSE" ; break ;
358 case SF_STR_TRACKNUMBER : name = "Tracknumber" ; break ;
359 case SF_STR_GENRE : name = "Genre" ; break ;
360
361 default : continue ;
362 } ;
363
364 vorbis_comment_add_tag (&vdata->vcomment, name, psf->strings.storage + psf->strings.data [k].offset) ;
365 } ;
366
367 /* set up the analysis state and auxiliary encoding storage */
368 vorbis_analysis_init (&vdata->vdsp, &vdata->vinfo) ;
369 vorbis_block_init (&vdata->vdsp, &vdata->vblock) ;
370
371 /*
372 ** Set up our packet->stream encoder.
373 ** Pick a random serial number ; that way we can more likely build
374 ** chained streams just by concatenation.
375 */
376
377 ogg_stream_init (&odata->ostream, psf_rand_int32 ()) ;
378
379 /* Vorbis streams begin with three headers ; the initial header (with
380 most of the codec setup parameters) which is mandated by the Ogg
381 bitstream spec. The second header holds any comment fields. The
382 third header holds the bitstream codebook. We merely need to
383 make the headers, then pass them to libvorbis one at a time ;
384 libvorbis handles the additional Ogg bitstream constraints */
385
386 { ogg_packet header ;
387 ogg_packet header_comm ;
388 ogg_packet header_code ;
389 int result ;
390
391 vorbis_analysis_headerout (&vdata->vdsp, &vdata->vcomment, &header, &header_comm, &header_code) ;
392 ogg_stream_packetin (&odata->ostream, &header) ; /* automatically placed in its own page */
393 ogg_stream_packetin (&odata->ostream, &header_comm) ;
394 ogg_stream_packetin (&odata->ostream, &header_code) ;
395
396 /* This ensures the actual
397 * audio data will start on a new page, as per spec
398 */
399 while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0)
400 { ogg_write_page (psf, &odata->opage) ;
401 } ;
402 }
403
404 return 0 ;
405 } /* vorbis_write_header */
406
407 static int
vorbis_close(SF_PRIVATE * psf)408 vorbis_close (SF_PRIVATE *psf)
409 { OGG_PRIVATE* odata = psf->container_data ;
410 VORBIS_PRIVATE *vdata = psf->codec_data ;
411
412 if (odata == NULL || vdata == NULL)
413 return 0 ;
414
415 /* Clean up this logical bitstream ; before exit we shuld see if we're
416 ** followed by another [chained]. */
417
418 if (psf->file.mode == SFM_WRITE)
419 {
420 if (psf->write_current <= 0)
421 vorbis_write_header (psf, 0) ;
422
423 vorbis_analysis_wrote (&vdata->vdsp, 0) ;
424 while (vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock) == 1)
425 {
426
427 /* analysis, assume we want to use bitrate management */
428 vorbis_analysis (&vdata->vblock, NULL) ;
429 vorbis_bitrate_addblock (&vdata->vblock) ;
430
431 while (vorbis_bitrate_flushpacket (&vdata->vdsp, &odata->opacket))
432 { /* weld the packet into the bitstream */
433 ogg_stream_packetin (&odata->ostream, &odata->opacket) ;
434
435 /* write out pages (if any) */
436 while (!odata->eos)
437 { int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
438 if (result == 0) break ;
439 ogg_write_page (psf, &odata->opage) ;
440
441 /* this could be set above, but for illustrative purposes, I do
442 it here (to show that vorbis does know where the stream ends) */
443
444 if (ogg_page_eos (&odata->opage)) odata->eos = 1 ;
445 }
446 }
447 }
448 }
449
450 /* ogg_page and ogg_packet structs always point to storage in
451 libvorbis. They are never freed or manipulated directly */
452
453 vorbis_block_clear (&vdata->vblock) ;
454 vorbis_dsp_clear (&vdata->vdsp) ;
455 vorbis_comment_clear (&vdata->vcomment) ;
456 vorbis_info_clear (&vdata->vinfo) ;
457
458 return 0 ;
459 } /* vorbis_close */
460
461 int
ogg_vorbis_open(SF_PRIVATE * psf)462 ogg_vorbis_open (SF_PRIVATE *psf)
463 { OGG_PRIVATE* odata = psf->container_data ;
464 VORBIS_PRIVATE* vdata ;
465 int error = 0 ;
466
467 if (odata == NULL)
468 { psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
469 return SFE_INTERNAL ;
470 } ;
471
472 vdata = calloc (1, sizeof (VORBIS_PRIVATE)) ;
473 psf->codec_data = vdata ;
474
475 if (psf->file.mode == SFM_RDWR)
476 return SFE_BAD_MODE_RW ;
477
478 psf_log_printf (psf, "Vorbis library version : %s\n", vorbis_version_string ()) ;
479
480 if (psf->file.mode == SFM_READ)
481 { if ((error = vorbis_read_header (psf)))
482 return error ;
483
484 psf->read_short = vorbis_read_s ;
485 psf->read_int = vorbis_read_i ;
486 psf->read_float = vorbis_read_f ;
487 psf->read_double = vorbis_read_d ;
488 } ;
489
490 psf->codec_close = vorbis_close ;
491 if (psf->file.mode == SFM_WRITE)
492 {
493 /* Set the default vorbis quality here. */
494 vdata->quality = 0.4 ;
495
496 psf->write_header = vorbis_write_header ;
497 psf->write_short = vorbis_write_s ;
498 psf->write_int = vorbis_write_i ;
499 psf->write_float = vorbis_write_f ;
500 psf->write_double = vorbis_write_d ;
501
502 psf->sf.frames = 0 ;
503 psf->datalength = 0 ;
504 psf->filelength = 0 ;
505 psf->dataoffset = 0 ;
506 psf->strings.flags = SF_STR_ALLOW_START ;
507 } ;
508
509 psf->seek = vorbis_seek ;
510 psf->command = vorbis_command ;
511 psf->byterate = vorbis_byterate ;
512 psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
513 psf->sf.sections = 1 ;
514
515 return error ;
516 } /* ogg_vorbis_open */
517
518 static int
vorbis_command(SF_PRIVATE * psf,int command,void * data,int datasize)519 vorbis_command (SF_PRIVATE *psf, int command, void * data, int datasize)
520 { VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
521
522 switch (command)
523 { case SFC_SET_COMPRESSION_LEVEL :
524 if (data == NULL || datasize != sizeof (double))
525 return SF_FALSE ;
526
527 if (psf->have_written)
528 return SF_FALSE ;
529
530 vdata->quality = 1.0 - *((double *) data) ;
531
532 /* Clip range. */
533 vdata->quality = SF_MAX (0.0, SF_MIN (1.0, vdata->quality)) ;
534
535 psf_log_printf (psf, "%s : Setting SFC_SET_VBR_ENCODING_QUALITY to %f.\n", __func__, vdata->quality) ;
536 return SF_TRUE ;
537
538 default :
539 return SF_FALSE ;
540 } ;
541
542 return SF_FALSE ;
543 } /* vorbis_command */
544
545 static int
vorbis_rnull(SF_PRIVATE * UNUSED (psf),int samples,void * UNUSED (vptr),int UNUSED (off),int channels,float ** UNUSED (pcm))546 vorbis_rnull (SF_PRIVATE *UNUSED (psf), int samples, void *UNUSED (vptr), int UNUSED (off) , int channels, float **UNUSED (pcm))
547 {
548 return samples * channels ;
549 } /* vorbis_rnull */
550
551 static int
vorbis_rshort(SF_PRIVATE * psf,int samples,void * vptr,int off,int channels,float ** pcm)552 vorbis_rshort (SF_PRIVATE *psf, int samples, void *vptr, int off, int channels, float **pcm)
553 {
554 short *ptr = (short*) vptr + off ;
555 int i = 0, j, n ;
556 if (psf->float_int_mult)
557 {
558 float inverse = 1.0 / psf->float_max ;
559 for (j = 0 ; j < samples ; j++)
560 for (n = 0 ; n < channels ; n++)
561 ptr [i++] = psf_lrintf ((pcm [n][j] * inverse) * 32767.0f) ;
562 }
563 else
564 {
565 for (j = 0 ; j < samples ; j++)
566 for (n = 0 ; n < channels ; n++)
567 ptr [i++] = psf_lrintf (pcm [n][j] * 32767.0f) ;
568 }
569 return i ;
570 } /* vorbis_rshort */
571
572 static int
vorbis_rint(SF_PRIVATE * psf,int samples,void * vptr,int off,int channels,float ** pcm)573 vorbis_rint (SF_PRIVATE *psf, int samples, void *vptr, int off, int channels, float **pcm)
574 {
575 int *ptr = (int*) vptr + off ;
576 int i = 0, j, n ;
577
578 if (psf->float_int_mult)
579 {
580 float inverse = 1.0 / psf->float_max ;
581 for (j = 0 ; j < samples ; j++)
582 for (n = 0 ; n < channels ; n++)
583 ptr [i++] = psf_lrintf ((pcm [n][j] * inverse) * 2147483647.0f) ;
584 }
585 else
586 {
587 for (j = 0 ; j < samples ; j++)
588 for (n = 0 ; n < channels ; n++)
589 ptr [i++] = psf_lrintf (pcm [n][j] * 2147483647.0f) ;
590 }
591 return i ;
592 } /* vorbis_rint */
593
594 static int
vorbis_rfloat(SF_PRIVATE * UNUSED (psf),int samples,void * vptr,int off,int channels,float ** pcm)595 vorbis_rfloat (SF_PRIVATE *UNUSED (psf), int samples, void *vptr, int off, int channels, float **pcm)
596 {
597 float *ptr = (float*) vptr + off ;
598 int i = 0, j, n ;
599 for (j = 0 ; j < samples ; j++)
600 for (n = 0 ; n < channels ; n++)
601 ptr [i++] = pcm [n][j] ;
602 return i ;
603 } /* vorbis_rfloat */
604
605 static int
vorbis_rdouble(SF_PRIVATE * UNUSED (psf),int samples,void * vptr,int off,int channels,float ** pcm)606 vorbis_rdouble (SF_PRIVATE *UNUSED (psf), int samples, void *vptr, int off, int channels, float **pcm)
607 {
608 double *ptr = (double*) vptr + off ;
609 int i = 0, j, n ;
610 for (j = 0 ; j < samples ; j++)
611 for (n = 0 ; n < channels ; n++)
612 ptr [i++] = pcm [n][j] ;
613 return i ;
614 } /* vorbis_rdouble */
615
616
617 static sf_count_t
vorbis_read_sample(SF_PRIVATE * psf,void * ptr,sf_count_t lens,convert_func * transfn)618 vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn)
619 { VORBIS_PRIVATE *vdata = psf->codec_data ;
620 OGG_PRIVATE *odata = psf->container_data ;
621 int len, samples, i = 0 , nn ;
622 float **pcm ;
623
624 len = lens / psf->sf.channels ;
625
626 while (len > 0)
627 { /*
628 ** pcm is a multichannel float vector. In stereo, for
629 ** example, pcm [0] is left, and pcm [1] is right. samples is
630 ** the size of each channel. Convert the float values
631 ** (-1.<=range<=1.) to whatever PCM format and write it out.
632 */
633 while ((samples = vorbis_synthesis_pcmout (&vdata->vdsp, &pcm)) > 0)
634 { if (samples > len) samples = len ;
635 i += transfn (psf, samples, ptr, i, psf->sf.channels, pcm) ;
636 len -= samples ;
637 /* tell libvorbis how many samples we actually consumed */
638 vorbis_synthesis_read (&vdata->vdsp, samples) ;
639 vdata->loc += samples ;
640 if (len == 0)
641 return i ; /* Is this necessary */
642 } ;
643
644 /* Out of samples, load the next packet. */
645 if (odata->pkt_indx == odata->pkt_len)
646 { /* Page out of packets, load and unpack the next page. */
647 nn = ogg_stream_unpack_page (psf, odata) ;
648 if (nn <= 0)
649 return i ;
650 if (nn == 2)
651 { /* Ran over a hole. loc is now out of date, need to recalculate. */
652 vdata->loc = odata->pkt [odata->pkt_len - 1].granulepos ;
653 vdata->loc -= vorbis_calculate_page_duration (psf) ;
654 }
655 } ;
656
657 /* Decode the packet */
658 if (vorbis_synthesis (&vdata->vblock, &(odata->pkt [odata->pkt_indx])) == 0) /* test for success! */
659 vorbis_synthesis_blockin (&vdata->vdsp, &vdata->vblock) ;
660 odata->pkt_indx++ ;
661 } ;
662
663 return i ;
664 } /* vorbis_read_sample */
665
666 static sf_count_t
vorbis_read_s(SF_PRIVATE * psf,short * ptr,sf_count_t lens)667 vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t lens)
668 { return vorbis_read_sample (psf, (void*) ptr, lens, vorbis_rshort) ;
669 } /* vorbis_read_s */
670
671 static sf_count_t
vorbis_read_i(SF_PRIVATE * psf,int * ptr,sf_count_t lens)672 vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t lens)
673 { return vorbis_read_sample (psf, (void*) ptr, lens, vorbis_rint) ;
674 } /* vorbis_read_i */
675
676 static sf_count_t
vorbis_read_f(SF_PRIVATE * psf,float * ptr,sf_count_t lens)677 vorbis_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t lens)
678 { return vorbis_read_sample (psf, (void*) ptr, lens, vorbis_rfloat) ;
679 } /* vorbis_read_f */
680
681 static sf_count_t
vorbis_read_d(SF_PRIVATE * psf,double * ptr,sf_count_t lens)682 vorbis_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t lens)
683 { return vorbis_read_sample (psf, (void*) ptr, lens, vorbis_rdouble) ;
684 } /* vorbis_read_d */
685
686 /*==============================================================================
687 */
688
689 static void
vorbis_write_samples(SF_PRIVATE * psf,OGG_PRIVATE * odata,VORBIS_PRIVATE * vdata,int in_frames)690 vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata, int in_frames)
691 {
692 vorbis_analysis_wrote (&vdata->vdsp, in_frames) ;
693
694 /*
695 ** Vorbis does some data preanalysis, then divvies up blocks for
696 ** more involved (potentially parallel) processing. Get a single
697 ** block for encoding now.
698 */
699 while (vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock) == 1)
700 {
701 /* analysis, assume we want to use bitrate management */
702 vorbis_analysis (&vdata->vblock, NULL) ;
703 vorbis_bitrate_addblock (&vdata->vblock) ;
704
705 while (vorbis_bitrate_flushpacket (&vdata->vdsp, &odata->opacket))
706 {
707 /* weld the packet into the bitstream */
708 ogg_stream_packetin (&odata->ostream, &odata->opacket) ;
709
710 /* write out pages (if any) */
711 while (!odata->eos)
712 { int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
713 if (result == 0)
714 break ;
715 ogg_write_page (psf, &odata->opage) ;
716
717 /* This could be set above, but for illustrative purposes, I do
718 ** it here (to show that vorbis does know where the stream ends) */
719 if (ogg_page_eos (&odata->opage))
720 odata->eos = 1 ;
721 } ;
722 } ;
723 } ;
724
725 vdata->loc += in_frames ;
726 } /* vorbis_write_data */
727
728
729 static sf_count_t
vorbis_write_s(SF_PRIVATE * psf,const short * ptr,sf_count_t lens)730 vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t lens)
731 {
732 int i, m, j = 0 ;
733 OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
734 VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
735 int in_frames = lens / psf->sf.channels ;
736 float **buffer = vorbis_analysis_buffer (&vdata->vdsp, in_frames) ;
737 for (i = 0 ; i < in_frames ; i++)
738 for (m = 0 ; m < psf->sf.channels ; m++)
739 buffer [m][i] = (float) (ptr [j++]) / 32767.0f ;
740
741 vorbis_write_samples (psf, odata, vdata, in_frames) ;
742
743 return lens ;
744 } /* vorbis_write_s */
745
746 static sf_count_t
vorbis_write_i(SF_PRIVATE * psf,const int * ptr,sf_count_t lens)747 vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t lens)
748 { int i, m, j = 0 ;
749 OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
750 VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
751 int in_frames = lens / psf->sf.channels ;
752 float **buffer = vorbis_analysis_buffer (&vdata->vdsp, in_frames) ;
753 for (i = 0 ; i < in_frames ; i++)
754 for (m = 0 ; m < psf->sf.channels ; m++)
755 buffer [m][i] = (float) (ptr [j++]) / 2147483647.0f ;
756
757 vorbis_write_samples (psf, odata, vdata, in_frames) ;
758
759 return lens ;
760 } /* vorbis_write_i */
761
762 static sf_count_t
vorbis_write_f(SF_PRIVATE * psf,const float * ptr,sf_count_t lens)763 vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t lens)
764 { int i, m, j = 0 ;
765 OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
766 VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
767 int in_frames = lens / psf->sf.channels ;
768 float **buffer = vorbis_analysis_buffer (&vdata->vdsp, in_frames) ;
769 for (i = 0 ; i < in_frames ; i++)
770 for (m = 0 ; m < psf->sf.channels ; m++)
771 buffer [m][i] = ptr [j++] ;
772
773 vorbis_write_samples (psf, odata, vdata, in_frames) ;
774
775 return lens ;
776 } /* vorbis_write_f */
777
778 static sf_count_t
vorbis_write_d(SF_PRIVATE * psf,const double * ptr,sf_count_t lens)779 vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t lens)
780 { int i, m, j = 0 ;
781 OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
782 VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
783 int in_frames = lens / psf->sf.channels ;
784 float **buffer = vorbis_analysis_buffer (&vdata->vdsp, in_frames) ;
785 for (i = 0 ; i < in_frames ; i++)
786 for (m = 0 ; m < psf->sf.channels ; m++)
787 buffer [m][i] = (float) ptr [j++] ;
788
789 vorbis_write_samples (psf, odata, vdata, in_frames) ;
790
791 return lens ;
792 } /* vorbis_write_d */
793
794 static sf_count_t
vorbis_seek(SF_PRIVATE * psf,int UNUSED (mode),sf_count_t offset)795 vorbis_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
796 { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
797 VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
798 sf_count_t target ;
799 int ret ;
800
801 if (odata == NULL || vdata == NULL)
802 return 0 ;
803
804 if (offset < 0)
805 { psf->error = SFE_BAD_SEEK ;
806 return ((sf_count_t) -1) ;
807 } ;
808
809 if (psf->file.mode == SFM_READ)
810 { target = offset + vdata->pcm_start ;
811
812 /*
813 ** If the end of the file is know, and the seek isn't for the near
814 ** future, do a search of the file for a good place to start.
815 */
816 ret = 0 ;
817 if ((vdata->pcm_end != (uint64_t) -1) &&
818 (target < vdata->loc || target - vdata->loc > (2 * psf->sf.samplerate)))
819 { uint64_t best_gp ;
820
821 best_gp = vdata->pcm_start ;
822
823 ret = ogg_stream_seek_page_search (psf, odata, target, vdata->pcm_start,
824 vdata->pcm_end, &best_gp, psf->dataoffset, vdata->last_page) ;
825 if (ret >= 0)
826 { ret = ogg_stream_unpack_page (psf, odata) ;
827 if (ret == 1)
828 { vdata->loc = best_gp ;
829 vorbis_synthesis_restart (&vdata->vdsp) ;
830 } ;
831 } ;
832 } ;
833
834 if (ret >= 0 && offset + (sf_count_t) vdata->pcm_start >= vdata->loc)
835 target = offset + vdata->pcm_start - vdata->loc ;
836 else
837 { /* Search failed (bad data?), reset to the beginning of the stream. */
838 ogg_stream_reset_serialno (&odata->ostream, odata->ostream.serialno) ;
839 odata->pkt_len = 0 ;
840 odata->pkt_indx = 0 ;
841 ogg_sync_fseek (psf, psf->dataoffset, SEEK_SET) ;
842 vdata->loc = 0 ;
843 vorbis_synthesis_restart (&vdata->vdsp) ;
844 target = offset ;
845 } ;
846
847 while (target > 0)
848 { sf_count_t m = target > 4096 ? 4096 : target ;
849
850 /*
851 ** Need to multiply by channels here because the seek is done in
852 ** terms of frames and the read function is done in terms of
853 ** samples.
854 */
855 vorbis_read_sample (psf, (void *) NULL, m * psf->sf.channels, vorbis_rnull) ;
856
857 target -= m ;
858 } ;
859
860 return vdata->loc - vdata->pcm_start ;
861 } ;
862
863 return 0 ;
864 } /* vorbis_seek */
865
866
867 static int
vorbis_byterate(SF_PRIVATE * psf)868 vorbis_byterate (SF_PRIVATE *psf)
869 {
870 if (psf->file.mode == SFM_READ)
871 return (psf->datalength * psf->sf.samplerate) / psf->sf.frames ;
872
873 return -1 ;
874 } /* vorbis_byterate */
875
876 static sf_count_t
vorbis_calculate_page_duration(SF_PRIVATE * psf)877 vorbis_calculate_page_duration (SF_PRIVATE *psf)
878 { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
879 VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
880 long thisblock, lastblock ;
881 sf_count_t duration ;
882 int i ;
883
884 lastblock = -1 ;
885 duration = 0 ;
886 for (i = 0 ; i < odata->pkt_len ; i++)
887 { thisblock = vorbis_packet_blocksize (&vdata->vinfo, &(odata->pkt [i])) ;
888 if (thisblock >= 0)
889 { if (lastblock != -1)
890 duration += (lastblock + thisblock) >> 2 ;
891 lastblock = thisblock ;
892 } ;
893 } ;
894
895 return duration ;
896 }
897
898 #else /* HAVE_EXTERNAL_XIPH_LIBS */
899
900 int
ogg_vorbis_open(SF_PRIVATE * psf)901 ogg_vorbis_open (SF_PRIVATE *psf)
902 {
903 psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Vorbis support.\n") ;
904 return SFE_UNIMPLEMENTED ;
905 } /* ogg_vorbis_open */
906
907 #endif
908