1/********************************************************************
2 *                                                                  *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7 *                                                                  *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
9 * by the Xiph.Org Foundation http://www.xiph.org/                  *
10 *                                                                  *
11 ********************************************************************
12
13 function: utility functions for vorbis codec test suite.
14 last mod: $Id: util.c 13293 2007-07-24 00:09:47Z erikd $
15
16 ********************************************************************/
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <math.h>
21#include <string.h>
22#include <errno.h>
23
24#include <vorbis/codec.h>
25#include <vorbis/vorbisenc.h>
26
27#include "write_read.h"
28
29/* The following function is basically a hacked version of the code in
30 * examples/encoder_example.c */
31void
32write_vorbis_data_or_die (const char *filename, int srate, float q, const float * data, int count, int ch)
33{
34  FILE * file ;
35  ogg_stream_state os;
36  ogg_page         og;
37  ogg_packet       op;
38  vorbis_info      vi;
39  vorbis_comment   vc;
40  vorbis_dsp_state vd;
41  vorbis_block     vb;
42
43  int eos = 0, ret;
44
45  if ((file = fopen (filename, "wb")) == NULL) {
46    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
47    exit (1) ;
48  }
49
50  /********** Encode setup ************/
51
52  vorbis_info_init (&vi);
53
54  ret = vorbis_encode_init_vbr (&vi,ch,srate,q);
55  if (ret) {
56    printf ("vorbis_encode_init_vbr return %d\n", ret) ;
57    exit (1) ;
58  }
59
60  vorbis_comment_init (&vc);
61  vorbis_comment_add_tag (&vc,"ENCODER","test/util.c");
62  vorbis_analysis_init (&vd,&vi);
63  vorbis_block_init (&vd,&vb);
64
65  ogg_stream_init (&os,12345678);
66
67  {
68    ogg_packet header;
69    ogg_packet header_comm;
70    ogg_packet header_code;
71
72    vorbis_analysis_headerout (&vd,&vc,&header,&header_comm,&header_code);
73    ogg_stream_packetin (&os,&header);
74    ogg_stream_packetin (&os,&header_comm);
75    ogg_stream_packetin (&os,&header_code);
76
77    /* Ensures the audio data will start on a new page. */
78    while (!eos){
79        int result = ogg_stream_flush (&os,&og);
80        if (result == 0)
81            break;
82        fwrite (og.header,1,og.header_len,file);
83        fwrite (og.body,1,og.body_len,file);
84    }
85
86  }
87
88  {
89    /* expose the buffer to submit data */
90    float **buffer = vorbis_analysis_buffer (&vd,count);
91    int i;
92
93    for(i=0;i<ch;i++)
94      memcpy (buffer [i], data, count * sizeof (float)) ;
95
96    /* tell the library how much we actually submitted */
97    vorbis_analysis_wrote (&vd,count);
98    vorbis_analysis_wrote (&vd,0);
99  }
100
101  while (vorbis_analysis_blockout (&vd,&vb) == 1) {
102    vorbis_analysis (&vb,NULL);
103    vorbis_bitrate_addblock (&vb);
104
105    while (vorbis_bitrate_flushpacket (&vd,&op)) {
106      ogg_stream_packetin (&os,&op);
107
108      while (!eos) {
109          int result = ogg_stream_pageout (&os,&og);
110          if (result == 0)
111              break;
112          fwrite (og.header,1,og.header_len,file);
113          fwrite (og.body,1,og.body_len,file);
114
115          if (ogg_page_eos (&og))
116              eos = 1;
117      }
118    }
119  }
120
121  ogg_stream_clear (&os);
122  vorbis_block_clear (&vb);
123  vorbis_dsp_clear (&vd);
124  vorbis_comment_clear (&vc);
125  vorbis_info_clear (&vi);
126
127 fclose (file) ;
128}
129
130/* The following function is basically a hacked version of the code in
131 * examples/decoder_example.c */
132void
133read_vorbis_data_or_die (const char *filename, int srate, float * data, int count)
134{
135  ogg_sync_state   oy;
136  ogg_stream_state os;
137  ogg_page         og;
138  ogg_packet       op;
139
140  vorbis_info      vi;
141  vorbis_comment   vc;
142  vorbis_dsp_state vd;
143  vorbis_block     vb;
144
145  FILE *file;
146  char *buffer;
147  int  bytes;
148  int eos = 0;
149  int i;
150  int read_total = 0 ;
151
152  if ((file = fopen (filename, "rb")) == NULL) {
153    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
154    exit (1) ;
155  }
156
157  ogg_sync_init (&oy);
158
159  {
160    /* fragile!  Assumes all of our headers will fit in the first 8kB,
161       which currently they will */
162    buffer = ogg_sync_buffer (&oy,8192);
163    bytes = fread (buffer,1,8192,file);
164    ogg_sync_wrote (&oy,bytes);
165
166    if(ogg_sync_pageout (&oy,&og) != 1) {
167      if(bytes < 8192) {
168        printf ("Out of data.\n") ;
169          goto done_decode ;
170      }
171
172      fprintf (stderr,"Input does not appear to be an Ogg bitstream.\n");
173      exit (1);
174    }
175
176    ogg_stream_init (&os,ogg_page_serialno(&og));
177
178    vorbis_info_init (&vi);
179    vorbis_comment_init (&vc);
180    if (ogg_stream_pagein (&os,&og) < 0) {
181      fprintf (stderr,"Error reading first page of Ogg bitstream data.\n");
182      exit (1);
183    }
184
185    if (ogg_stream_packetout(&os,&op) != 1) {
186      fprintf (stderr,"Error reading initial header packet.\n");
187      exit (1);
188    }
189
190    if (vorbis_synthesis_headerin (&vi,&vc,&op) < 0) {
191      fprintf (stderr,"This Ogg bitstream does not contain Vorbis "
192          "audio data.\n");
193      exit (1);
194    }
195
196    i = 0;
197    while ( i < 2) {
198      while (i < 2) {
199
200        int result = ogg_sync_pageout (&oy,&og);
201        if(result == 0)
202          break;
203        if(result==1) {
204          ogg_stream_pagein(&os,&og);
205
206          while (i < 2) {
207            result = ogg_stream_packetout (&os,&op);
208            if (result == 0) break;
209            if (result < 0) {
210              fprintf (stderr,"Corrupt secondary header.  Exiting.\n");
211              exit(1);
212            }
213            vorbis_synthesis_headerin (&vi,&vc,&op);
214            i++;
215          }
216        }
217      }
218
219      buffer = ogg_sync_buffer (&oy,4096);
220      bytes = fread (buffer,1,4096,file);
221      if (bytes == 0 && i < 2) {
222        fprintf (stderr,"End of file before finding all Vorbis headers!\n");
223        exit (1);
224      }
225
226      ogg_sync_wrote (&oy,bytes);
227    }
228
229    if (vi.rate != srate) {
230      printf ("\n\nError : File '%s' has sample rate of %ld when it should be %d.\n\n", filename, vi.rate, srate);
231      exit (1) ;
232    }
233
234    vorbis_synthesis_init (&vd,&vi);
235    vorbis_block_init (&vd,&vb);
236
237    while(!eos) {
238      while (!eos) {
239        int result = ogg_sync_pageout (&oy,&og);
240        if (result == 0)
241          break;
242        if (result < 0) {
243          fprintf (stderr,"Corrupt or missing data in bitstream; "
244                   "continuing...\n");
245        } else {
246          ogg_stream_pagein (&os,&og);
247          while (1) {
248            result = ogg_stream_packetout (&os,&op);
249
250            if (result == 0)
251              break;
252            if (result < 0) {
253              /* no reason to complain; already complained above */
254            } else {
255              float **pcm;
256              int samples;
257
258              if (vorbis_synthesis (&vb,&op) == 0)
259                vorbis_synthesis_blockin(&vd,&vb);
260              while ((samples = vorbis_synthesis_pcmout (&vd,&pcm)) > 0 && read_total < count) {
261                int bout = samples < count ? samples : count;
262                bout = read_total + bout > count ? count - read_total : bout;
263
264                memcpy (data + read_total, pcm[0], bout * sizeof (float)) ;
265
266                vorbis_synthesis_read (&vd,bout);
267                read_total += bout ;
268              }
269            }
270          }
271
272          if (ogg_page_eos (&og)) eos = 1;
273        }
274      }
275
276      if (!eos) {
277        buffer = ogg_sync_buffer (&oy,4096);
278        bytes = fread (buffer,1,4096,file);
279        ogg_sync_wrote (&oy,bytes);
280        if (bytes == 0) eos = 1;
281      }
282    }
283
284    ogg_stream_clear (&os);
285
286    vorbis_block_clear (&vb);
287    vorbis_dsp_clear (&vd);
288    vorbis_comment_clear (&vc);
289    vorbis_info_clear (&vi);
290  }
291done_decode:
292
293  /* OK, clean up the framer */
294  ogg_sync_clear (&oy);
295
296  fclose (file) ;
297}
298
299