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