1 /*
2 * Copyright 2015 The Emscripten Authors. All rights reserved.
3 * Emscripten is available under two separate licenses, the MIT license and the
4 * University of Illinois/NCSA Open Source License. Both these licenses can be
5 * found in the LICENSE file.
6 */
7
8 /********************************************************************
9 * *
10 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
11 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
12 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
13 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
14 * *
15 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
16 * by the Xiph.Org Foundation http://www.xiph.org/ *
17 * *
18 ********************************************************************
19
20 function: vorbis coded test suite using vorbisfile
21 last mod: $Id$
22
23 ********************************************************************/
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <math.h>
28 #include <string.h>
29 #include <errno.h>
30
31 #include <vorbis/codec.h>
32 #include <vorbis/vorbisenc.h>
33
34
35 #define DATA_LEN 2048
36
37 #define MAX(a,b) ((a) > (b) ? (a) : (b))
38 #define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
39
40 /* The following function is basically a hacked version of the code in
41 * examples/encoder_example.c */
42 void
write_vorbis_data_or_die(const char * filename,int srate,float q,const float * data,int count,int ch)43 write_vorbis_data_or_die (const char *filename, int srate, float q, const float * data, int count, int ch)
44 {
45 FILE * file ;
46 ogg_stream_state os;
47 ogg_page og;
48 ogg_packet op;
49 vorbis_info vi;
50 vorbis_comment vc;
51 vorbis_dsp_state vd;
52 vorbis_block vb;
53
54 int eos = 0, ret;
55
56 if ((file = fopen (filename, "wb")) == NULL) {
57 printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
58 exit (1) ;
59 }
60
61 /********** Encode setup ************/
62
63 vorbis_info_init (&vi);
64
65 ret = vorbis_encode_init_vbr (&vi,ch,srate,q);
66 if (ret) {
67 printf ("vorbis_encode_init_vbr return %d\n", ret) ;
68 exit (1) ;
69 }
70
71 vorbis_comment_init (&vc);
72 vorbis_comment_add_tag (&vc,"ENCODER","test/util.c");
73 vorbis_analysis_init (&vd,&vi);
74 vorbis_block_init (&vd,&vb);
75
76 ogg_stream_init (&os,12345678);
77
78 {
79 ogg_packet header;
80 ogg_packet header_comm;
81 ogg_packet header_code;
82
83 vorbis_analysis_headerout (&vd,&vc,&header,&header_comm,&header_code);
84 ogg_stream_packetin (&os,&header);
85 ogg_stream_packetin (&os,&header_comm);
86 ogg_stream_packetin (&os,&header_code);
87
88 /* Ensures the audio data will start on a new page. */
89 while (!eos){
90 int result = ogg_stream_flush (&os,&og);
91 if (result == 0)
92 break;
93 fwrite (og.header,1,og.header_len,file);
94 fwrite (og.body,1,og.body_len,file);
95 }
96
97 }
98
99 {
100 /* expose the buffer to submit data */
101 float **buffer = vorbis_analysis_buffer (&vd,count);
102 int i;
103
104 for(i=0;i<ch;i++)
105 memcpy (buffer [i], data, count * sizeof (float)) ;
106
107 /* tell the library how much we actually submitted */
108 vorbis_analysis_wrote (&vd,count);
109 vorbis_analysis_wrote (&vd,0);
110 }
111
112 while (vorbis_analysis_blockout (&vd,&vb) == 1) {
113 vorbis_analysis (&vb,NULL);
114 vorbis_bitrate_addblock (&vb);
115
116 while (vorbis_bitrate_flushpacket (&vd,&op)) {
117 ogg_stream_packetin (&os,&op);
118
119 while (!eos) {
120 int result = ogg_stream_pageout (&os,&og);
121 if (result == 0)
122 break;
123 fwrite (og.header,1,og.header_len,file);
124 fwrite (og.body,1,og.body_len,file);
125
126 if (ogg_page_eos (&og))
127 eos = 1;
128 }
129 }
130 }
131
132 ogg_stream_clear (&os);
133 vorbis_block_clear (&vb);
134 vorbis_dsp_clear (&vd);
135 vorbis_comment_clear (&vc);
136 vorbis_info_clear (&vi);
137
138 fclose (file) ;
139 }
140
141 /* The following function is basically a hacked version of the code in
142 * examples/decoder_example.c */
143 void
read_vorbis_data_or_die(const char * filename,int srate,float * data,int count)144 read_vorbis_data_or_die (const char *filename, int srate, float * data, int count)
145 {
146 ogg_sync_state oy;
147 ogg_stream_state os;
148 ogg_page og;
149 ogg_packet op;
150
151 vorbis_info vi;
152 vorbis_comment vc;
153 vorbis_dsp_state vd;
154 vorbis_block vb;
155
156 FILE *file;
157 char *buffer;
158 int bytes;
159 int eos = 0;
160 int i;
161 int read_total = 0 ;
162
163 if ((file = fopen (filename, "rb")) == NULL) {
164 printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
165 exit (1) ;
166 }
167
168 ogg_sync_init (&oy);
169
170 {
171 /* fragile! Assumes all of our headers will fit in the first 8kB,
172 which currently they will */
173 buffer = ogg_sync_buffer (&oy,8192);
174 bytes = fread (buffer,1,8192,file);
175 ogg_sync_wrote (&oy,bytes);
176
177 if(ogg_sync_pageout (&oy,&og) != 1) {
178 if(bytes < 8192) {
179 printf ("Out of data.\n") ;
180 goto done_decode ;
181 }
182
183 fprintf (stderr,"Input does not appear to be an Ogg bitstream.\n");
184 exit (1);
185 }
186
187 ogg_stream_init (&os,ogg_page_serialno(&og));
188
189 vorbis_info_init (&vi);
190 vorbis_comment_init (&vc);
191 if (ogg_stream_pagein (&os,&og) < 0) {
192 fprintf (stderr,"Error reading first page of Ogg bitstream data.\n");
193 exit (1);
194 }
195
196 if (ogg_stream_packetout(&os,&op) != 1) {
197 fprintf (stderr,"Error reading initial header packet.\n");
198 exit (1);
199 }
200
201 if (vorbis_synthesis_headerin (&vi,&vc,&op) < 0) {
202 fprintf (stderr,"This Ogg bitstream does not contain Vorbis "
203 "audio data.\n");
204 exit (1);
205 }
206
207 i = 0;
208 while ( i < 2) {
209 while (i < 2) {
210
211 int result = ogg_sync_pageout (&oy,&og);
212 if(result == 0)
213 break;
214 if(result==1) {
215 ogg_stream_pagein(&os,&og);
216
217 while (i < 2) {
218 result = ogg_stream_packetout (&os,&op);
219 if (result == 0) break;
220 if (result < 0) {
221 fprintf (stderr,"Corrupt secondary header. Exiting.\n");
222 exit(1);
223 }
224 vorbis_synthesis_headerin (&vi,&vc,&op);
225 i++;
226 }
227 }
228 }
229
230 buffer = ogg_sync_buffer (&oy,4096);
231 bytes = fread (buffer,1,4096,file);
232 if (bytes == 0 && i < 2) {
233 fprintf (stderr,"End of file before finding all Vorbis headers!\n");
234 exit (1);
235 }
236
237 ogg_sync_wrote (&oy,bytes);
238 }
239
240 if (vi.rate != srate) {
241 printf ("\n\nError : File '%s' has sample rate of %ld when it should be %d.\n\n", filename, vi.rate, srate);
242 exit (1) ;
243 }
244
245 vorbis_synthesis_init (&vd,&vi);
246 vorbis_block_init (&vd,&vb);
247
248 while(!eos) {
249 while (!eos) {
250 int result = ogg_sync_pageout (&oy,&og);
251 if (result == 0)
252 break;
253 if (result < 0) {
254 fprintf (stderr,"Corrupt or missing data in bitstream; "
255 "continuing...\n");
256 } else {
257 ogg_stream_pagein (&os,&og);
258 while (1) {
259 result = ogg_stream_packetout (&os,&op);
260
261 if (result == 0)
262 break;
263 if (result < 0) {
264 /* no reason to complain; already complained above */
265 } else {
266 float **pcm;
267 int samples;
268
269 if (vorbis_synthesis (&vb,&op) == 0)
270 vorbis_synthesis_blockin(&vd,&vb);
271 while ((samples = vorbis_synthesis_pcmout (&vd,&pcm)) > 0 && read_total < count) {
272 int bout = samples < count ? samples : count;
273 bout = read_total + bout > count ? count - read_total : bout;
274
275 memcpy (data + read_total, pcm[0], bout * sizeof (float)) ;
276
277 vorbis_synthesis_read (&vd,bout);
278 read_total += bout ;
279 }
280 }
281 }
282
283 if (ogg_page_eos (&og)) eos = 1;
284 }
285 }
286
287 if (!eos) {
288 buffer = ogg_sync_buffer (&oy,4096);
289 bytes = fread (buffer,1,4096,file);
290 ogg_sync_wrote (&oy,bytes);
291 if (bytes == 0) eos = 1;
292 }
293 }
294
295 ogg_stream_clear (&os);
296
297 vorbis_block_clear (&vb);
298 vorbis_dsp_clear (&vd);
299 vorbis_comment_clear (&vc);
300 vorbis_info_clear (&vi);
301 }
302 done_decode:
303
304 /* OK, clean up the framer */
305 ogg_sync_clear (&oy);
306
307 fclose (file) ;
308 }
309
310 void
gen_windowed_sine(float * data,int len,float maximum)311 gen_windowed_sine (float *data, int len, float maximum)
312 { int k ;
313
314 memset (data, 0, len * sizeof (float)) ;
315
316 len /= 2 ;
317
318 for (k = 0 ; k < len ; k++)
319 { data [k] = sin (2.0 * k * M_PI * 1.0 / 32.0 + 0.4) ;
320
321 /* Apply Hanning Window. */
322 data [k] *= maximum * (0.5 - 0.5 * cos (2.0 * M_PI * k / ((len) - 1))) ;
323 }
324
325 return ;
326 }
327
328 void
set_data_in(float * data,unsigned len,float value)329 set_data_in (float * data, unsigned len, float value)
330 { unsigned k ;
331
332 for (k = 0 ; k < len ; k++)
333 data [k] = value ;
334 }
335
336 static int check_output (const float * data_in, unsigned len, float allowable);
337
338 int
main(void)339 main(void){
340 static float data_out [DATA_LEN] ;
341 static float data_in [DATA_LEN] ;
342
343 /* Do safest and most used sample rates first. */
344 int sample_rates [] = { 44100, 48000, 32000, 22050, 16000, 96000 } ;
345 unsigned k ;
346 int errors = 0 ;
347 int ch;
348
349 gen_windowed_sine (data_out, ARRAY_LEN (data_out), 0.95);
350
351 for(ch=1;ch<=8;ch++){
352 float q=-.05;
353 printf("\nTesting %d channel%s\n\n",ch,ch==1?"":"s");
354 while(q<1.){
355 for (k = 0 ; k < ARRAY_LEN (sample_rates); k ++) {
356 char filename [64] ;
357 snprintf (filename, sizeof (filename), "vorbis_%dch_q%.1f_%u.ogg", ch,q*10,sample_rates [k]);
358
359 printf (" %-20s : ", filename);
360 fflush (stdout);
361
362 /* Set to know value. */
363 set_data_in (data_in, ARRAY_LEN (data_in), 3.141);
364
365 write_vorbis_data_or_die (filename, sample_rates [k], q, data_out, ARRAY_LEN (data_out),ch);
366 read_vorbis_data_or_die (filename, sample_rates [k], data_in, ARRAY_LEN (data_in));
367
368 if (check_output (data_in, ARRAY_LEN (data_in), (.15f - .1f*q)) != 0)
369 errors ++ ;
370 else {
371 puts ("ok");
372 remove (filename);
373 }
374 }
375 q+=.1;
376 }
377 }
378
379 if (errors)
380 exit (1);
381
382 printf("ALL OK\n");
383
384 return 0;
385 }
386
387 static int
check_output(const float * data_in,unsigned len,float allowable)388 check_output (const float * data_in, unsigned len, float allowable)
389 {
390 float max_abs = 0.0 ;
391 unsigned k ;
392
393 for (k = 0 ; k < len ; k++) {
394 float temp = fabs (data_in [k]);
395 max_abs = MAX (max_abs, temp);
396 }
397
398 if (max_abs < 0.95-allowable) {
399 printf ("Error : max_abs (%f) too small.\n", max_abs);
400 return 1 ;
401 } else if (max_abs > .95+allowable) {
402 printf ("Error : max_abs (%f) too big.\n", max_abs);
403 return 1 ;
404 }
405
406 return 0 ;
407 }
408
409