• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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