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