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