~ubuntu-branches/ubuntu/hardy/speex/hardy-security

« back to all changes in this revision

Viewing changes to src/speexdec.c

  • Committer: Bazaar Package Importer
  • Author(s): A. Maitland Bottoms
  • Date: 2005-02-26 22:33:22 UTC
  • Revision ID: james.westby@ubuntu.com-20050226223322-vc6sdoshrqjxfh9c
Tags: upstream-1.1.6
ImportĀ upstreamĀ versionĀ 1.1.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2002-2003 Jean-Marc Valin 
 
2
   File: speexdec.c
 
3
 
 
4
   Redistribution and use in source and binary forms, with or without
 
5
   modification, are permitted provided that the following conditions
 
6
   are met:
 
7
   
 
8
   - Redistributions of source code must retain the above copyright
 
9
   notice, this list of conditions and the following disclaimer.
 
10
   
 
11
   - Redistributions in binary form must reproduce the above copyright
 
12
   notice, this list of conditions and the following disclaimer in the
 
13
   documentation and/or other materials provided with the distribution.
 
14
   
 
15
   - Neither the name of the Xiph.org Foundation nor the names of its
 
16
   contributors may be used to endorse or promote products derived from
 
17
   this software without specific prior written permission.
 
18
   
 
19
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
20
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
21
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
22
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
 
23
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
24
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
25
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
26
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 
27
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 
28
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
29
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
30
*/
 
31
 
 
32
#ifdef HAVE_CONFIG_H
 
33
# include "config.h"
 
34
#endif
 
35
 
 
36
#include <stdio.h>
 
37
#if !defined WIN32 && !defined _WIN32
 
38
#include <unistd.h>
 
39
#include <getopt.h>
 
40
#endif
 
41
#ifndef HAVE_GETOPT_LONG
 
42
#include "getopt_win.h"
 
43
#endif
 
44
#include <stdlib.h>
 
45
#include <string.h>
 
46
 
 
47
#include <speex/speex.h>
 
48
#include <ogg/ogg.h>
 
49
 
 
50
#if defined WIN32 || defined _WIN32
 
51
#include <windows.h>
 
52
#include "getopt_win.h"
 
53
#include "wave_out.h"
 
54
/* We need the following two to set stdout to binary */
 
55
#include <io.h>
 
56
#include <fcntl.h>
 
57
#endif
 
58
#include <math.h>
 
59
 
 
60
#ifdef __MINGW32__
 
61
#include "wave_out.c"
 
62
#endif
 
63
 
 
64
#ifdef HAVE_SYS_SOUNDCARD_H
 
65
#include <sys/soundcard.h>
 
66
#include <sys/types.h>
 
67
#include <sys/stat.h>
 
68
#include <fcntl.h>
 
69
#include <sys/ioctl.h>
 
70
 
 
71
#elif defined HAVE_SYS_AUDIOIO_H
 
72
#include <sys/types.h>
 
73
#include <fcntl.h>
 
74
#include <sys/ioctl.h>
 
75
#include <sys/audioio.h>
 
76
#ifndef AUDIO_ENCODING_SLINEAR
 
77
#define AUDIO_ENCODING_SLINEAR AUDIO_ENCODING_LINEAR /* Solaris */
 
78
#endif
 
79
 
 
80
#endif
 
81
 
 
82
#include <string.h>
 
83
#include "wav_io.h"
 
84
#include <speex/speex_header.h>
 
85
#include <speex/speex_stereo.h>
 
86
#include <speex/speex_callbacks.h>
 
87
#include "misc.h"
 
88
 
 
89
#ifdef DISABLE_GLOBAL_POINTERS
 
90
#include <speex/speex_noglobals.h>
 
91
#endif
 
92
 
 
93
#define MAX_FRAME_SIZE 2000
 
94
 
 
95
#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
 
96
                           ((buf[base+2]<<16)&0xff0000)| \
 
97
                           ((buf[base+1]<<8)&0xff00)| \
 
98
                            (buf[base]&0xff))
 
99
 
 
100
static void print_comments(char *comments, int length)
 
101
{
 
102
   char *c=comments;
 
103
   int len, i, nb_fields;
 
104
   char *end;
 
105
   
 
106
   if (length<8)
 
107
   {
 
108
      fprintf (stderr, "Invalid/corrupted comments\n");
 
109
      return;
 
110
   }
 
111
   end = c+length;
 
112
   len=readint(c, 0);
 
113
   c+=4;
 
114
   if (c+len>end)
 
115
   {
 
116
      fprintf (stderr, "Invalid/corrupted comments\n");
 
117
      return;
 
118
   }
 
119
   fwrite(c, 1, len, stderr);
 
120
   c+=len;
 
121
   fprintf (stderr, "\n");
 
122
   if (c+4>end)
 
123
   {
 
124
      fprintf (stderr, "Invalid/corrupted comments\n");
 
125
      return;
 
126
   }
 
127
   nb_fields=readint(c, 0);
 
128
   c+=4;
 
129
   for (i=0;i<nb_fields;i++)
 
130
   {
 
131
      if (c+4>end)
 
132
      {
 
133
         fprintf (stderr, "Invalid/corrupted comments\n");
 
134
         return;
 
135
      }
 
136
      len=readint(c, 0);
 
137
      c+=4;
 
138
      if (c+len>end)
 
139
      {
 
140
         fprintf (stderr, "Invalid/corrupted comments\n");
 
141
         return;
 
142
      }
 
143
      fwrite(c, 1, len, stderr);
 
144
      c+=len;
 
145
      fprintf (stderr, "\n");
 
146
   }
 
147
}
 
148
 
 
149
FILE *out_file_open(char *outFile, int rate, int *channels)
 
150
{
 
151
   FILE *fout=NULL;
 
152
   /*Open output file*/
 
153
   if (strlen(outFile)==0)
 
154
   {
 
155
#if defined HAVE_SYS_SOUNDCARD_H
 
156
      int audio_fd, format, stereo;
 
157
      audio_fd=open("/dev/dsp", O_WRONLY);
 
158
      if (audio_fd<0)
 
159
      {
 
160
         perror("Cannot open /dev/dsp");
 
161
         exit(1);         
 
162
      }
 
163
 
 
164
      format=AFMT_S16_NE;
 
165
      if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1)
 
166
      {
 
167
         perror("SNDCTL_DSP_SETFMT");
 
168
         close(audio_fd);
 
169
         exit(1);
 
170
      }
 
171
 
 
172
      stereo=0;
 
173
      if (*channels==2)
 
174
         stereo=1;
 
175
      if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1)
 
176
      {
 
177
         perror("SNDCTL_DSP_STEREO");
 
178
         close(audio_fd);
 
179
         exit(1);
 
180
      }
 
181
      if (stereo!=0)
 
182
      {
 
183
         if (*channels==1)
 
184
            fprintf (stderr, "Cannot set mono mode, will decode in stereo\n");
 
185
         *channels=2;
 
186
      }
 
187
 
 
188
      if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate)==-1)
 
189
      {
 
190
         perror("SNDCTL_DSP_SPEED");
 
191
         close(audio_fd);
 
192
         exit(1);
 
193
      }
 
194
      fout = fdopen(audio_fd, "w");
 
195
#elif defined HAVE_SYS_AUDIOIO_H
 
196
      audio_info_t info;
 
197
      int audio_fd;
 
198
      
 
199
      audio_fd = open("/dev/audio", O_WRONLY);
 
200
      if (audio_fd<0)
 
201
      {
 
202
         perror("Cannot open /dev/audio");
 
203
         exit(1);
 
204
      }
 
205
 
 
206
      AUDIO_INITINFO(&info);
 
207
#ifdef AUMODE_PLAY    /* NetBSD/OpenBSD */
 
208
      info.mode = AUMODE_PLAY;
 
209
#endif
 
210
      info.play.encoding = AUDIO_ENCODING_SLINEAR;
 
211
      info.play.precision = 16;
 
212
      info.play.sample_rate = rate;
 
213
      info.play.channels = *channels;
 
214
      
 
215
      if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0)
 
216
      {
 
217
         perror ("AUDIO_SETINFO");
 
218
         exit(1);
 
219
      }
 
220
      fout = fdopen(audio_fd, "w");
 
221
#elif defined WIN32 || defined _WIN32
 
222
      {
 
223
         unsigned int speex_channels = *channels;
 
224
         if (Set_WIN_Params (INVALID_FILEDESC, rate, SAMPLE_SIZE, speex_channels))
 
225
         {
 
226
            fprintf (stderr, "Can't access %s\n", "WAVE OUT");
 
227
            exit(1);
 
228
         }
 
229
      }
 
230
#else
 
231
      fprintf (stderr, "No soundcard support\n");
 
232
      exit(1);
 
233
#endif
 
234
   } else {
 
235
      if (strcmp(outFile,"-")==0)
 
236
      {
 
237
#if defined WIN32 || defined _WIN32
 
238
         _setmode(_fileno(stdout), _O_BINARY);
 
239
#endif
 
240
         fout=stdout;
 
241
      }
 
242
      else 
 
243
      {
 
244
         fout = fopen(outFile, "wb");
 
245
         if (!fout)
 
246
         {
 
247
            perror(outFile);
 
248
            exit(1);
 
249
         }
 
250
         if (strcmp(outFile+strlen(outFile)-4,".wav")==0 || strcmp(outFile+strlen(outFile)-4,".WAV")==0)
 
251
            write_wav_header(fout, rate, *channels, 0, 0);
 
252
      }
 
253
   }
 
254
   return fout;
 
255
}
 
256
 
 
257
void usage()
 
258
{
 
259
   printf ("Usage: speexdec [options] input_file.spx [output_file]\n");
 
260
   printf ("\n");
 
261
   printf ("Decodes a Speex file and produce a WAV file or raw file\n");
 
262
   printf ("\n");
 
263
   printf ("input_file can be:\n");
 
264
   printf ("  filename.spx         regular Speex file\n");
 
265
   printf ("  -                    stdin\n");
 
266
   printf ("\n");  
 
267
   printf ("output_file can be:\n");
 
268
   printf ("  filename.wav         Wav file\n");
 
269
   printf ("  filename.*           Raw PCM file (any extension other that .wav)\n");
 
270
   printf ("  -                    stdout\n");
 
271
   printf ("  (nothing)            Will be played to soundcard\n");
 
272
   printf ("\n");  
 
273
   printf ("Options:\n");
 
274
   printf (" --enh                 Enable perceptual enhancement (default)\n");
 
275
   printf (" --no-enh              Disable perceptual enhancement\n");
 
276
   printf (" --force-nb            Force decoding in narrowband\n");
 
277
   printf (" --force-wb            Force decoding in wideband\n");
 
278
   printf (" --force-uwb           Force decoding in ultra-wideband\n");
 
279
   printf (" --mono                Force decoding in mono\n");
 
280
   printf (" --stereo              Force decoding in stereo\n");
 
281
   printf (" --rate n              Force decoding at sampling rate n Hz\n");
 
282
   printf (" --packet-loss n       Simulate n %% random packet loss\n");
 
283
   printf (" -V                    Verbose mode (show bit-rate)\n"); 
 
284
   printf (" -h, --help            This help\n");
 
285
   printf (" -v, --version         Version information\n");
 
286
   printf (" --pf                  Deprecated, use --enh instead\n");
 
287
   printf (" --no-pf               Deprecated, use --no-enh instead\n");
 
288
   printf ("\n");
 
289
   printf ("More information is available from the Speex site: http://www.speex.org\n");
 
290
   printf ("\n");
 
291
   printf ("Please report bugs to the mailing list `speex-dev@xiph.org'.\n");
 
292
}
 
293
 
 
294
void version()
 
295
{
 
296
   printf ("speexdec (Speex decoder) version " SPEEX_VERSION " (compiled " __DATE__ ")\n");
 
297
   printf ("Copyright (C) 2002-2003 Jean-Marc Valin\n");
 
298
}
 
299
 
 
300
void version_short()
 
301
{
 
302
   printf ("speexdec version " SPEEX_VERSION "\n");
 
303
   printf ("Copyright (C) 2002-2003 Jean-Marc Valin\n");
 
304
}
 
305
 
 
306
static void *process_header(ogg_packet *op, int enh_enabled, int *frame_size, int *rate, int *nframes, int forceMode, int *channels, SpeexStereoState *stereo, int *extra_headers, int quiet)
 
307
{
 
308
   void *st;
 
309
   const SpeexMode *mode;
 
310
   SpeexHeader *header;
 
311
   int modeID;
 
312
   SpeexCallback callback;
 
313
      
 
314
   header = speex_packet_to_header((char*)op->packet, op->bytes);
 
315
   if (!header)
 
316
   {
 
317
      fprintf (stderr, "Cannot read header\n");
 
318
      return NULL;
 
319
   }
 
320
   if (header->mode >= SPEEX_NB_MODES)
 
321
   {
 
322
      fprintf (stderr, "Mode number %d does not (yet/any longer) exist in this version\n", 
 
323
               header->mode);
 
324
      return NULL;
 
325
   }
 
326
      
 
327
   modeID = header->mode;
 
328
   if (forceMode!=-1)
 
329
      modeID = forceMode;
 
330
 
 
331
#ifdef DISABLE_GLOBAL_POINTERS
 
332
   mode = speex_mode_new (modeID);
 
333
#else
 
334
   mode = speex_mode_list[modeID];
 
335
#endif
 
336
   
 
337
   if (header->speex_version_id > 1)
 
338
   {
 
339
      fprintf (stderr, "This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", header->speex_version_id);
 
340
      return NULL;
 
341
   }
 
342
 
 
343
   if (mode->bitstream_version < header->mode_bitstream_version)
 
344
   {
 
345
      fprintf (stderr, "The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n");
 
346
      return NULL;
 
347
   }
 
348
   if (mode->bitstream_version > header->mode_bitstream_version) 
 
349
   {
 
350
      fprintf (stderr, "The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n");
 
351
      return NULL;
 
352
   }
 
353
   
 
354
   st = speex_decoder_init(mode);
 
355
   if (!st)
 
356
   {
 
357
      fprintf (stderr, "Decoder initialization failed.\n");
 
358
      return NULL;
 
359
   }
 
360
   speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled);
 
361
   speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size);
 
362
 
 
363
   if (!(*channels==1))
 
364
   {
 
365
      callback.callback_id = SPEEX_INBAND_STEREO;
 
366
      callback.func = speex_std_stereo_request_handler;
 
367
      callback.data = stereo;
 
368
      speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback);
 
369
   }
 
370
   if (!*rate)
 
371
      *rate = header->rate;
 
372
   /* Adjust rate if --force-* options are used */
 
373
   if (forceMode!=-1)
 
374
   {
 
375
      if (header->mode < forceMode)
 
376
         *rate <<= (forceMode - header->mode);
 
377
      if (header->mode > forceMode)
 
378
         *rate >>= (header->mode - forceMode);
 
379
   }
 
380
 
 
381
   speex_decoder_ctl(st, SPEEX_SET_SAMPLING_RATE, rate);
 
382
 
 
383
   *nframes = header->frames_per_packet;
 
384
 
 
385
   if (*channels==-1)
 
386
      *channels = header->nb_channels;
 
387
   
 
388
   if (!quiet)
 
389
   {
 
390
      fprintf (stderr, "Decoding %d Hz audio using %s mode", 
 
391
               *rate, mode->modeName);
 
392
 
 
393
      if (*channels==1)
 
394
         fprintf (stderr, " (mono");
 
395
      else
 
396
         fprintf (stderr, " (stereo");
 
397
      
 
398
      if (header->vbr)
 
399
         fprintf (stderr, ", VBR)\n");
 
400
      else
 
401
         fprintf(stderr, ")\n");
 
402
      /*fprintf (stderr, "Decoding %d Hz audio at %d bps using %s mode\n", 
 
403
       *rate, mode->bitrate, mode->modeName);*/
 
404
   }
 
405
 
 
406
   *extra_headers = header->extra_headers;
 
407
 
 
408
   free(header);
 
409
   return st;
 
410
}
 
411
 
 
412
int main(int argc, char **argv)
 
413
{
 
414
   int c;
 
415
   int option_index = 0;
 
416
   char *inFile, *outFile;
 
417
   FILE *fin, *fout=NULL;
 
418
   short out[MAX_FRAME_SIZE];
 
419
   short output[MAX_FRAME_SIZE];
 
420
   int frame_size=0;
 
421
   void *st=NULL;
 
422
   SpeexBits bits;
 
423
   int packet_count=0;
 
424
   int stream_init = 0;
 
425
   int quiet = 0;
 
426
   ogg_int64_t page_granule=0, last_granule=0;
 
427
   int skip_samples=0, page_nb_packets;
 
428
   struct option long_options[] =
 
429
   {
 
430
      {"help", no_argument, NULL, 0},
 
431
      {"quiet", no_argument, NULL, 0},
 
432
      {"version", no_argument, NULL, 0},
 
433
      {"version-short", no_argument, NULL, 0},
 
434
      {"enh", no_argument, NULL, 0},
 
435
      {"no-enh", no_argument, NULL, 0},
 
436
      {"pf", no_argument, NULL, 0},
 
437
      {"no-pf", no_argument, NULL, 0},
 
438
      {"force-nb", no_argument, NULL, 0},
 
439
      {"force-wb", no_argument, NULL, 0},
 
440
      {"force-uwb", no_argument, NULL, 0},
 
441
      {"rate", required_argument, NULL, 0},
 
442
      {"mono", no_argument, NULL, 0},
 
443
      {"stereo", no_argument, NULL, 0},
 
444
      {"packet-loss", required_argument, NULL, 0},
 
445
      {0, 0, 0, 0}
 
446
   };
 
447
   ogg_sync_state oy;
 
448
   ogg_page       og;
 
449
   ogg_packet     op;
 
450
   ogg_stream_state os;
 
451
   int enh_enabled;
 
452
   int nframes=2;
 
453
   int print_bitrate=0;
 
454
   int close_in=0;
 
455
   int eos=0;
 
456
   int forceMode=-1;
 
457
   int audio_size=0;
 
458
   float loss_percent=-1;
 
459
   SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
 
460
   int channels=-1;
 
461
   int rate=0;
 
462
   int extra_headers;
 
463
   int wav_format=0;
 
464
 
 
465
   enh_enabled = 1;
 
466
 
 
467
   /*Process options*/
 
468
   while(1)
 
469
   {
 
470
      c = getopt_long (argc, argv, "hvV",
 
471
                       long_options, &option_index);
 
472
      if (c==-1)
 
473
         break;
 
474
      
 
475
      switch(c)
 
476
      {
 
477
      case 0:
 
478
         if (strcmp(long_options[option_index].name,"help")==0)
 
479
         {
 
480
            usage();
 
481
            exit(0);
 
482
         } else if (strcmp(long_options[option_index].name,"quiet")==0)
 
483
         {
 
484
            quiet = 1;
 
485
         } else if (strcmp(long_options[option_index].name,"version")==0)
 
486
         {
 
487
            version();
 
488
            exit(0);
 
489
         } else if (strcmp(long_options[option_index].name,"version-short")==0)
 
490
         {
 
491
            version_short();
 
492
            exit(0);
 
493
         } else if (strcmp(long_options[option_index].name,"enh")==0)
 
494
         {
 
495
            enh_enabled=1;
 
496
         } else if (strcmp(long_options[option_index].name,"no-enh")==0)
 
497
         {
 
498
            enh_enabled=0;
 
499
         } else if (strcmp(long_options[option_index].name,"pf")==0)
 
500
         {
 
501
            fprintf (stderr, "--pf is deprecated, use --enh instead\n");
 
502
            enh_enabled=1;
 
503
         } else if (strcmp(long_options[option_index].name,"no-pf")==0)
 
504
         {
 
505
            fprintf (stderr, "--no-pf is deprecated, use --no-enh instead\n");
 
506
            enh_enabled=0;
 
507
         } else if (strcmp(long_options[option_index].name,"force-nb")==0)
 
508
         {
 
509
            forceMode=0;
 
510
         } else if (strcmp(long_options[option_index].name,"force-wb")==0)
 
511
         {
 
512
            forceMode=1;
 
513
         } else if (strcmp(long_options[option_index].name,"force-uwb")==0)
 
514
         {
 
515
            forceMode=2;
 
516
         } else if (strcmp(long_options[option_index].name,"mono")==0)
 
517
         {
 
518
            channels=1;
 
519
         } else if (strcmp(long_options[option_index].name,"stereo")==0)
 
520
         {
 
521
            channels=2;
 
522
         } else if (strcmp(long_options[option_index].name,"rate")==0)
 
523
         {
 
524
            rate=atoi (optarg);
 
525
         } else if (strcmp(long_options[option_index].name,"packet-loss")==0)
 
526
         {
 
527
            loss_percent = atof(optarg);
 
528
         }
 
529
         break;
 
530
      case 'h':
 
531
         usage();
 
532
         exit(0);
 
533
         break;
 
534
      case 'v':
 
535
         version();
 
536
         exit(0);
 
537
         break;
 
538
      case 'V':
 
539
         print_bitrate=1;
 
540
         break;
 
541
      case '?':
 
542
         usage();
 
543
         exit(1);
 
544
         break;
 
545
      }
 
546
   }
 
547
   if (argc-optind!=2 && argc-optind!=1)
 
548
   {
 
549
      usage();
 
550
      exit(1);
 
551
   }
 
552
   inFile=argv[optind];
 
553
 
 
554
   if (argc-optind==2)
 
555
      outFile=argv[optind+1];
 
556
   else
 
557
      outFile = "";
 
558
   wav_format = strlen(outFile)>=4 && (
 
559
                                       strcmp(outFile+strlen(outFile)-4,".wav")==0
 
560
                                       || strcmp(inFile+strlen(inFile)-4,".WAV")==0);
 
561
   /*Open input file*/
 
562
   if (strcmp(inFile, "-")==0)
 
563
   {
 
564
#if defined WIN32 || defined _WIN32
 
565
      _setmode(_fileno(stdin), _O_BINARY);
 
566
#endif
 
567
      fin=stdin;
 
568
   }
 
569
   else 
 
570
   {
 
571
      fin = fopen(inFile, "rb");
 
572
      if (!fin)
 
573
      {
 
574
         perror(inFile);
 
575
         exit(1);
 
576
      }
 
577
      close_in=1;
 
578
   }
 
579
 
 
580
 
 
581
   /*Init Ogg data struct*/
 
582
   ogg_sync_init(&oy);
 
583
   
 
584
   speex_bits_init(&bits);
 
585
   /*Main decoding loop*/
 
586
   while (1)
 
587
   {
 
588
      char *data;
 
589
      int i, j, nb_read;
 
590
      /*Get the ogg buffer for writing*/
 
591
      data = ogg_sync_buffer(&oy, 200);
 
592
      /*Read bitstream from input file*/
 
593
      nb_read = fread(data, sizeof(char), 200, fin);      
 
594
      ogg_sync_wrote(&oy, nb_read);
 
595
 
 
596
      /*Loop for all complete pages we got (most likely only one)*/
 
597
      while (ogg_sync_pageout(&oy, &og)==1)
 
598
      {
 
599
         int packet_no;
 
600
         if (stream_init == 0) {
 
601
            ogg_stream_init(&os, ogg_page_serialno(&og));
 
602
            stream_init = 1;
 
603
         }
 
604
         /*Add page to the bitstream*/
 
605
         ogg_stream_pagein(&os, &og);
 
606
         page_granule = ogg_page_granulepos(&og);
 
607
         page_nb_packets = ogg_page_packets(&og);
 
608
         if (page_granule>0 && frame_size)
 
609
         {
 
610
            skip_samples = page_nb_packets*frame_size*nframes - (page_granule-last_granule);
 
611
            if (ogg_page_eos(&og))
 
612
               skip_samples = -skip_samples;
 
613
            /*else if (!ogg_page_bos(&og))
 
614
               skip_samples = 0;*/
 
615
         } else
 
616
         {
 
617
            skip_samples = 0;
 
618
         }
 
619
         /*printf ("page granulepos: %d %d %d\n", skip_samples, page_nb_packets, (int)page_granule);*/
 
620
         last_granule = page_granule;
 
621
         /*Extract all available packets*/
 
622
         packet_no=0;
 
623
         while (!eos && ogg_stream_packetout(&os, &op)==1)
 
624
         {
 
625
            /*If first packet, process as Speex header*/
 
626
            if (packet_count==0)
 
627
            {
 
628
               st = process_header(&op, enh_enabled, &frame_size, &rate, &nframes, forceMode, &channels, &stereo, &extra_headers, quiet);
 
629
               if (!nframes)
 
630
                  nframes=1;
 
631
               if (!st)
 
632
                  exit(1);
 
633
               fout = out_file_open(outFile, rate, &channels);
 
634
 
 
635
            } else if (packet_count==1)
 
636
            {
 
637
               if (!quiet)
 
638
                  print_comments((char*)op.packet, op.bytes);
 
639
            } else if (packet_count<=1+extra_headers)
 
640
            {
 
641
               /* Ignore extra headers */
 
642
            } else {
 
643
               int lost=0;
 
644
               packet_no++;
 
645
               if (loss_percent>0 && 100*((float)rand())/RAND_MAX<loss_percent)
 
646
                  lost=1;
 
647
 
 
648
               /*End of stream condition*/
 
649
               if (op.e_o_s)
 
650
                  eos=1;
 
651
 
 
652
               /*Copy Ogg packet to Speex bitstream*/
 
653
               speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
 
654
               for (j=0;j!=nframes;j++)
 
655
               {
 
656
                  int ret;
 
657
                  /*Decode frame*/
 
658
                  if (!lost)
 
659
                     ret = speex_decode_int(st, &bits, output);
 
660
                  else
 
661
                     ret = speex_decode_int(st, NULL, output);
 
662
 
 
663
                  /*for (i=0;i<frame_size*channels;i++)
 
664
                    printf ("%d\n", (int)output[i]);*/
 
665
 
 
666
                  if (ret==-1)
 
667
                     break;
 
668
                  if (ret==-2)
 
669
                  {
 
670
                     fprintf (stderr, "Decoding error: corrupted stream?\n");
 
671
                     break;
 
672
                  }
 
673
                  if (speex_bits_remaining(&bits)<0)
 
674
                  {
 
675
                     fprintf (stderr, "Decoding overflow: corrupted stream?\n");
 
676
                     break;
 
677
                  }
 
678
                  if (channels==2)
 
679
                     speex_decode_stereo_int(output, frame_size, &stereo);
 
680
 
 
681
                  if (print_bitrate) {
 
682
                     int tmp;
 
683
                     char ch=13;
 
684
                     speex_decoder_ctl(st, SPEEX_GET_BITRATE, &tmp);
 
685
                     fputc (ch, stderr);
 
686
                     fprintf (stderr, "Bitrate is use: %d bps     ", tmp);
 
687
                  }
 
688
                  /*Convert to short and save to output file*/
 
689
                  if (strlen(outFile)!=0)
 
690
                  {
 
691
                     for (i=0;i<frame_size*channels;i++)
 
692
                        out[i]=le_short(output[i]);
 
693
                  } else {
 
694
                     for (i=0;i<frame_size*channels;i++)
 
695
                        out[i]=output[i];
 
696
                  }
 
697
                  {
 
698
                     int frame_offset = 0;
 
699
                     int new_frame_size = frame_size;
 
700
                     /*printf ("packet %d %d\n", packet_no, skip_samples);*/
 
701
                     if (packet_no == 1 && j==0 && skip_samples > 0)
 
702
                     {
 
703
                        /*printf ("chopping first packet\n");*/
 
704
                        new_frame_size -= skip_samples;
 
705
                        frame_offset = skip_samples;
 
706
                     }
 
707
                     if (packet_no == page_nb_packets && skip_samples < 0)
 
708
                     {
 
709
                        int packet_length = nframes*frame_size+skip_samples;
 
710
                        new_frame_size = packet_length - j*frame_size;
 
711
                        if (new_frame_size<0)
 
712
                           new_frame_size = 0;
 
713
                        if (new_frame_size>frame_size)
 
714
                           new_frame_size = frame_size;
 
715
                        /*printf ("chopping end: %d %d %d\n", new_frame_size, packet_length, packet_no);*/
 
716
                     }
 
717
                     if (new_frame_size)
 
718
                     {  
 
719
#if defined WIN32 || defined _WIN32
 
720
                        if (strlen(outFile)==0)
 
721
                           WIN_Play_Samples (out+frame_offset*channels, sizeof(short) * new_frame_size*channels);
 
722
                        else
 
723
#endif
 
724
                           fwrite(out+frame_offset*channels, sizeof(short), new_frame_size*channels, fout);
 
725
                  
 
726
                        audio_size+=sizeof(short)*new_frame_size*channels;
 
727
                     }
 
728
                  }
 
729
               }
 
730
            }
 
731
            packet_count++;
 
732
         }
 
733
      }
 
734
      if (feof(fin))
 
735
         break;
 
736
 
 
737
   }
 
738
 
 
739
   if (wav_format)
 
740
   {
 
741
      if (fseek(fout,4,SEEK_SET)==0)
 
742
      {
 
743
         int tmp;
 
744
         tmp = le_int(audio_size+36);
 
745
         fwrite(&tmp,4,1,fout);
 
746
         if (fseek(fout,32,SEEK_CUR)==0)
 
747
         {
 
748
            tmp = le_int(audio_size);
 
749
            fwrite(&tmp,4,1,fout);
 
750
         } else
 
751
         {
 
752
            fprintf (stderr, "First seek worked, second didn't\n");
 
753
         }
 
754
      } else {
 
755
         fprintf (stderr, "Cannot seek on wave file, size will be incorrect\n");
 
756
      }
 
757
   }
 
758
 
 
759
   if (st)
 
760
      speex_decoder_destroy(st);
 
761
   else 
 
762
   {
 
763
      fprintf (stderr, "This doesn't look like a Speex file\n");
 
764
   }
 
765
   speex_bits_destroy(&bits);
 
766
   if (stream_init)
 
767
      ogg_stream_clear(&os);
 
768
   ogg_sync_clear(&oy);
 
769
 
 
770
#if defined WIN32 || defined _WIN32
 
771
   if (strlen(outFile)==0)
 
772
      WIN_Audio_close ();
 
773
#endif
 
774
 
 
775
   if (close_in)
 
776
      fclose(fin);
 
777
   if (fout != NULL)
 
778
      fclose(fout);   
 
779
 
 
780
   return 0;
 
781
}