le_int now inline and returns a signed value. be_int is gone (no use)
[speexdsp.git] / src / speexenc.c
1 /* Copyright (C) 2002-2006 Jean-Marc Valin 
2    File: speexenc.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 #include <time.h>
47
48 #include <speex/speex.h>
49 #include <ogg/ogg.h>
50 #include "wav_io.h"
51 #include <speex/speex_header.h>
52 #include <speex/speex_stereo.h>
53 #include <speex/speex_preprocess.h>
54
55 #if defined WIN32 || defined _WIN32
56 #include "getopt_win.h"
57 /* We need the following two to set stdout to binary */
58 #include <io.h>
59 #include <fcntl.h>
60 #endif
61
62 #include "skeleton.h"
63
64
65 void comment_init(char **comments, int* length, char *vendor_string);
66 void comment_add(char **comments, int* length, char *tag, char *val);
67
68
69 /*Write an Ogg page to a file pointer*/
70 int oe_write_page(ogg_page *page, FILE *fp)
71 {
72    int written;
73    written = fwrite(page->header,1,page->header_len, fp);
74    written += fwrite(page->body,1,page->body_len, fp);
75    
76    return written;
77 }
78
79 #define MAX_FRAME_SIZE 2000
80 #define MAX_FRAME_BYTES 2000
81
82 /* Convert input audio bits, endians and channels */
83 static int read_samples(FILE *fin,int frame_size, int bits, int channels, int lsb, short * input, char *buff, spx_int32_t *size)
84 {   
85    unsigned char in[MAX_FRAME_BYTES*2];
86    int i;
87    short *s;
88    int nb_read;
89
90    if (size && *size<=0)
91    {
92       return 0;
93    }
94    /*Read input audio*/
95    if (size)
96       *size -= bits/8*channels*frame_size;
97    if (buff)
98    {
99       for (i=0;i<12;i++)
100          in[i]=buff[i];
101       nb_read = fread(in+12,1,bits/8*channels*frame_size-12, fin) + 12;
102       if (size)
103          *size += 12;
104    } else {
105       nb_read = fread(in,1,bits/8*channels* frame_size, fin);
106    }
107    nb_read /= bits/8*channels;
108
109    /*fprintf (stderr, "%d\n", nb_read);*/
110    if (nb_read==0)
111       return 0;
112
113    s=(short*)in;
114    if(bits==8)
115    {
116       /* Convert 8->16 bits */
117       for(i=frame_size*channels-1;i>=0;i--)
118       {
119          s[i]=(in[i]<<8)^0x8000;
120       }
121    } else
122    {
123       /* convert to our endian format */
124       for(i=0;i<frame_size*channels;i++)
125       {
126          if(lsb) 
127             s[i]=le_short(s[i]); 
128          else
129             s[i]=be_short(s[i]);
130       }
131    }
132
133    /* FIXME: This is probably redundent now */
134    /* copy to float input buffer */
135    for (i=0;i<frame_size*channels;i++)
136    {
137       input[i]=(short)s[i];
138    }
139
140    for (i=nb_read*channels;i<frame_size*channels;i++)
141    {
142       input[i]=0;
143    }
144
145
146    return nb_read;
147 }
148
149 void add_fishead_packet (ogg_stream_state *os) {
150
151    fishead_packet fp;
152
153    memset(&fp, 0, sizeof(fp));
154    fp.ptime_n = 0;
155    fp.ptime_d = 1000;
156    fp.btime_n = 0;
157    fp.btime_d = 1000;
158
159    add_fishead_to_stream(os, &fp);
160 }
161
162 /*
163  * Adds the fishead packets in the skeleton output stream along with the e_o_s packet
164  */
165 void add_fisbone_packet (ogg_stream_state *os, spx_int32_t serialno, SpeexHeader *header) {
166
167    fisbone_packet fp;
168
169    memset(&fp, 0, sizeof(fp));
170    fp.serial_no = serialno;
171    fp.nr_header_packet = 2 + header->extra_headers;
172    fp.granule_rate_n = header->rate;
173    fp.granule_rate_d = 1;
174    fp.start_granule = 0;
175    fp.preroll = 3;
176    fp.granule_shift = 0;
177
178    add_message_header_field(&fp, "Content-Type", "audio/x-speex");
179
180    add_fisbone_to_stream(os, &fp);
181 }
182
183 void version()
184 {
185    printf ("speexenc (Speex encoder) version " SPEEX_VERSION " (compiled " __DATE__ ")\n");
186    printf ("Copyright (C) 2002-2006 Jean-Marc Valin\n");
187 }
188
189 void version_short()
190 {
191    printf ("speexenc version " SPEEX_VERSION "\n");
192    printf ("Copyright (C) 2002-2006 Jean-Marc Valin\n");
193 }
194
195 void usage()
196 {
197    printf ("Usage: speexenc [options] input_file output_file\n");
198    printf ("\n");
199    printf ("Encodes input_file using Speex. It can read the WAV or raw files.\n");
200    printf ("\n");
201    printf ("input_file can be:\n");
202    printf ("  filename.wav      wav file\n");
203    printf ("  filename.*        Raw PCM file (any extension other than .wav)\n");
204    printf ("  -                 stdin\n");
205    printf ("\n");  
206    printf ("output_file can be:\n");
207    printf ("  filename.spx      Speex file\n");
208    printf ("  -                 stdout\n");
209    printf ("\n");  
210    printf ("Options:\n");
211    printf (" -n, --narrowband   Narrowband (8 kHz) input file\n"); 
212    printf (" -w, --wideband     Wideband (16 kHz) input file\n"); 
213    printf (" -u, --ultra-wideband \"Ultra-wideband\" (32 kHz) input file\n"); 
214    printf (" --quality n        Encoding quality (0-10), default 8\n"); 
215    printf (" --bitrate n        Encoding bit-rate (use bit-rate n or lower)\n"); 
216    printf (" --vbr              Enable variable bit-rate (VBR)\n"); 
217    printf (" --vbr-max-bitrate  Set max VBR bit-rate allowed\n"); 
218    printf (" --abr rate         Enable average bit-rate (ABR) at rate bps\n"); 
219    printf (" --vad              Enable voice activity detection (VAD)\n"); 
220    printf (" --dtx              Enable file-based discontinuous transmission (DTX)\n"); 
221    printf (" --comp n           Set encoding complexity (0-10), default 3\n"); 
222    printf (" --nframes n        Number of frames per Ogg packet (1-10), default 1\n"); 
223    printf (" --denoise          Denoise the input before encoding\n"); 
224    printf (" --agc              Apply adaptive gain control (AGC) before encoding\n"); 
225    printf (" --skeleton         Outputs ogg skeleton metadata (may cause incompatibilities)\n");
226    printf (" --comment          Add the given string as an extra comment. This may be\n");
227    printf ("                     used multiple times\n");
228    printf (" --author           Author of this track\n");
229    printf (" --title            Title for this track\n");
230    printf (" -h, --help         This help\n"); 
231    printf (" -v, --version      Version information\n"); 
232    printf (" -V                 Verbose mode (show bit-rate)\n"); 
233    printf ("Raw input options:\n");
234    printf (" --rate n           Sampling rate for raw input\n"); 
235    printf (" --stereo           Consider raw input as stereo\n"); 
236    printf (" --le               Raw input is little-endian\n"); 
237    printf (" --be               Raw input is big-endian\n"); 
238    printf (" --8bit             Raw input is 8-bit unsigned\n"); 
239    printf (" --16bit            Raw input is 16-bit signed\n"); 
240    printf ("Default raw PCM input is 16-bit, little-endian, mono\n"); 
241    printf ("\n");
242    printf ("More information is available from the Speex site: http://www.speex.org\n");
243    printf ("\n");
244    printf ("Please report bugs to the mailing list `speex-dev@xiph.org'.\n");
245 }
246
247
248 int main(int argc, char **argv)
249 {
250    int nb_samples, total_samples=0, nb_encoded;
251    int c;
252    int option_index = 0;
253    char *inFile, *outFile;
254    FILE *fin, *fout;
255    short input[MAX_FRAME_SIZE];
256    spx_int32_t frame_size;
257    int quiet=0;
258    spx_int32_t vbr_enabled=0;
259    spx_int32_t vbr_max=0;
260    int abr_enabled=0;
261    spx_int32_t vad_enabled=0;
262    spx_int32_t dtx_enabled=0;
263    int nbBytes;
264    const SpeexMode *mode=NULL;
265    int modeID = -1;
266    void *st;
267    SpeexBits bits;
268    char cbits[MAX_FRAME_BYTES];
269    int with_skeleton = 0;
270    struct option long_options[] =
271    {
272       {"wideband", no_argument, NULL, 0},
273       {"ultra-wideband", no_argument, NULL, 0},
274       {"narrowband", no_argument, NULL, 0},
275       {"vbr", no_argument, NULL, 0},
276       {"vbr-max-bitrate", required_argument, NULL, 0},
277       {"abr", required_argument, NULL, 0},
278       {"vad", no_argument, NULL, 0},
279       {"dtx", no_argument, NULL, 0},
280       {"quality", required_argument, NULL, 0},
281       {"bitrate", required_argument, NULL, 0},
282       {"nframes", required_argument, NULL, 0},
283       {"comp", required_argument, NULL, 0},
284       {"denoise", no_argument, NULL, 0},
285       {"agc", no_argument, NULL, 0},
286       {"skeleton",no_argument,NULL, 0},
287       {"help", no_argument, NULL, 0},
288       {"quiet", no_argument, NULL, 0},
289       {"le", no_argument, NULL, 0},
290       {"be", no_argument, NULL, 0},
291       {"8bit", no_argument, NULL, 0},
292       {"16bit", no_argument, NULL, 0},
293       {"stereo", no_argument, NULL, 0},
294       {"rate", required_argument, NULL, 0},
295       {"version", no_argument, NULL, 0},
296       {"version-short", no_argument, NULL, 0},
297       {"comment", required_argument, NULL, 0},
298       {"author", required_argument, NULL, 0},
299       {"title", required_argument, NULL, 0},
300       {0, 0, 0, 0}
301    };
302    int print_bitrate=0;
303    spx_int32_t rate=0;
304    spx_int32_t size;
305    int chan=1;
306    int fmt=16;
307    spx_int32_t quality=-1;
308    float vbr_quality=-1;
309    int lsb=1;
310    ogg_stream_state os;
311    ogg_stream_state so; /* ogg stream for skeleton bitstream */
312    ogg_page              og;
313    ogg_packet            op;
314    int bytes_written=0, ret, result;
315    int id=-1;
316    SpeexHeader header;
317    int nframes=1;
318    spx_int32_t complexity=3;
319    char *vendor_string = "Encoded with Speex " SPEEX_VERSION;
320    char *comments;
321    int comments_length;
322    int close_in=0, close_out=0;
323    int eos=0;
324    spx_int32_t bitrate=0;
325    double cumul_bits=0, enc_frames=0;
326    char first_bytes[12];
327    int wave_input=0;
328    spx_int32_t tmp;
329    SpeexPreprocessState *preprocess = NULL;
330    int denoise_enabled=0, agc_enabled=0;
331    spx_int32_t lookahead = 0;
332    
333    comment_init(&comments, &comments_length, vendor_string);
334
335    /*Process command-line options*/
336    while(1)
337    {
338       c = getopt_long (argc, argv, "nwuhvV",
339                        long_options, &option_index);
340       if (c==-1)
341          break;
342       
343       switch(c)
344       {
345       case 0:
346          if (strcmp(long_options[option_index].name,"narrowband")==0)
347          {
348             modeID = SPEEX_MODEID_NB;
349          } else if (strcmp(long_options[option_index].name,"wideband")==0)
350          {
351             modeID = SPEEX_MODEID_WB;
352          } else if (strcmp(long_options[option_index].name,"ultra-wideband")==0)
353          {
354             modeID = SPEEX_MODEID_UWB;
355          } else if (strcmp(long_options[option_index].name,"vbr")==0)
356          {
357             vbr_enabled=1;
358          } else if (strcmp(long_options[option_index].name,"vbr-max-bitrate")==0)
359          {
360             vbr_max=atoi(optarg);
361             if (vbr_max<1)
362             {
363                fprintf (stderr, "Invalid VBR max bit-rate value: %d\n", vbr_max);
364                exit(1);
365             }
366          } else if (strcmp(long_options[option_index].name,"abr")==0)
367          {
368             abr_enabled=atoi(optarg);
369             if (!abr_enabled)
370             {
371                fprintf (stderr, "Invalid ABR value: %d\n", abr_enabled);
372                exit(1);
373             }
374          } else if (strcmp(long_options[option_index].name,"vad")==0)
375          {
376             vad_enabled=1;
377          } else if (strcmp(long_options[option_index].name,"dtx")==0)
378          {
379             dtx_enabled=1;
380          } else if (strcmp(long_options[option_index].name,"quality")==0)
381          {
382             quality = atoi (optarg);
383             vbr_quality=atof(optarg);
384          } else if (strcmp(long_options[option_index].name,"bitrate")==0)
385          {
386             bitrate = atoi (optarg);
387          } else if (strcmp(long_options[option_index].name,"nframes")==0)
388          {
389             nframes = atoi (optarg);
390             if (nframes<1)
391                nframes=1;
392             if (nframes>10)
393                nframes=10;
394          } else if (strcmp(long_options[option_index].name,"comp")==0)
395          {
396             complexity = atoi (optarg);
397          } else if (strcmp(long_options[option_index].name,"denoise")==0)
398          {
399             denoise_enabled=1;
400          } else if (strcmp(long_options[option_index].name,"agc")==0)
401          {
402             agc_enabled=1;
403          } else if (strcmp(long_options[option_index].name,"skeleton")==0)
404          {
405             with_skeleton=1;
406          } else if (strcmp(long_options[option_index].name,"help")==0)
407          {
408             usage();
409             exit(0);
410          } else if (strcmp(long_options[option_index].name,"quiet")==0)
411          {
412             quiet = 1;
413          } else if (strcmp(long_options[option_index].name,"version")==0)
414          {
415             version();
416             exit(0);
417          } else if (strcmp(long_options[option_index].name,"version-short")==0)
418          {
419             version_short();
420             exit(0);
421          } else if (strcmp(long_options[option_index].name,"le")==0)
422          {
423             lsb=1;
424          } else if (strcmp(long_options[option_index].name,"be")==0)
425          {
426             lsb=0;
427          } else if (strcmp(long_options[option_index].name,"8bit")==0)
428          {
429             fmt=8;
430          } else if (strcmp(long_options[option_index].name,"16bit")==0)
431          {
432             fmt=16;
433          } else if (strcmp(long_options[option_index].name,"stereo")==0)
434          {
435             chan=2;
436          } else if (strcmp(long_options[option_index].name,"rate")==0)
437          {
438             rate=atoi (optarg);
439          } else if (strcmp(long_options[option_index].name,"comment")==0)
440          {
441            if (!strchr(optarg, '='))
442            {
443              fprintf (stderr, "Invalid comment: %s\n", optarg);
444              fprintf (stderr, "Comments must be of the form name=value\n");
445              exit(1);
446            }
447            comment_add(&comments, &comments_length, NULL, optarg); 
448          } else if (strcmp(long_options[option_index].name,"author")==0)
449          {
450            comment_add(&comments, &comments_length, "author=", optarg); 
451          } else if (strcmp(long_options[option_index].name,"title")==0)
452          {
453            comment_add(&comments, &comments_length, "title=", optarg); 
454          }
455
456          break;
457       case 'n':
458          modeID = SPEEX_MODEID_NB;
459          break;
460       case 'h':
461          usage();
462          exit(0);
463          break;
464       case 'v':
465          version();
466          exit(0);
467          break;
468       case 'V':
469          print_bitrate=1;
470          break;
471       case 'w':
472          modeID = SPEEX_MODEID_WB;
473          break;
474       case 'u':
475          modeID = SPEEX_MODEID_UWB;
476          break;
477       case '?':
478          usage();
479          exit(1);
480          break;
481       }
482    }
483    if (argc-optind!=2)
484    {
485       usage();
486       exit(1);
487    }
488    inFile=argv[optind];
489    outFile=argv[optind+1];
490
491    /*Initialize Ogg stream struct*/
492    srand(time(NULL));
493    if (ogg_stream_init(&os, rand())==-1)
494    {
495       fprintf(stderr,"Error: stream init failed\n");
496       exit(1);
497    }
498    if (with_skeleton && ogg_stream_init(&so, rand())==-1)
499    {
500       fprintf(stderr,"Error: stream init failed\n");
501       exit(1);
502    }
503
504    if (strcmp(inFile, "-")==0)
505    {
506 #if defined WIN32 || defined _WIN32
507          _setmode(_fileno(stdin), _O_BINARY);
508 #endif
509       fin=stdin;
510    }
511    else 
512    {
513       fin = fopen(inFile, "rb");
514       if (!fin)
515       {
516          perror(inFile);
517          exit(1);
518       }
519       close_in=1;
520    }
521
522    {
523       fread(first_bytes, 1, 12, fin);
524       if (strncmp(first_bytes,"RIFF",4)==0 && strncmp(first_bytes,"RIFF",4)==0)
525       {
526          if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1)
527             exit(1);
528          wave_input=1;
529          lsb=1; /* CHECK: exists big-endian .wav ?? */
530       }
531    }
532
533    if (modeID==-1 && !rate)
534    {
535       /* By default, use narrowband/8 kHz */
536       modeID = SPEEX_MODEID_NB;
537       rate=8000;
538    } else if (modeID!=-1 && rate)
539    {
540       mode = speex_lib_get_mode (modeID);
541       if (rate>48000)
542       {
543          fprintf (stderr, "Error: sampling rate too high: %d Hz, try down-sampling\n", rate);
544          exit(1);
545       } else if (rate>25000)
546       {
547          if (modeID != SPEEX_MODEID_UWB)
548          {
549             fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try ultra-wideband instead\n", mode->modeName , rate);
550          }
551       } else if (rate>12500)
552       {
553          if (modeID != SPEEX_MODEID_WB)
554          {
555             fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try wideband instead\n", mode->modeName , rate);
556          }
557       } else if (rate>=6000)
558       {
559          if (modeID != SPEEX_MODEID_NB)
560          {
561             fprintf (stderr, "Warning: Trying to encode in %s at %d Hz. I'll do it but I suggest you try narrowband instead\n", mode->modeName , rate);
562          }
563       } else {
564          fprintf (stderr, "Error: sampling rate too low: %d Hz\n", rate);
565          exit(1);
566       }
567    } else if (modeID==-1)
568    {
569       if (rate>48000)
570       {
571          fprintf (stderr, "Error: sampling rate too high: %d Hz, try down-sampling\n", rate);
572          exit(1);
573       } else if (rate>25000)
574       {
575          modeID = SPEEX_MODEID_UWB;
576       } else if (rate>12500)
577       {
578          modeID = SPEEX_MODEID_WB;
579       } else if (rate>=6000)
580       {
581          modeID = SPEEX_MODEID_NB;
582       } else {
583          fprintf (stderr, "Error: Sampling rate too low: %d Hz\n", rate);
584          exit(1);
585       }
586    } else if (!rate)
587    {
588       if (modeID == SPEEX_MODEID_NB)
589          rate=8000;
590       else if (modeID == SPEEX_MODEID_WB)
591          rate=16000;
592       else if (modeID == SPEEX_MODEID_UWB)
593          rate=32000;
594    }
595
596    if (!quiet)
597       if (rate!=8000 && rate!=16000 && rate!=32000)
598          fprintf (stderr, "Warning: Speex is only optimized for 8, 16 and 32 kHz. It will still work at %d Hz but your mileage may vary\n", rate); 
599
600    if (!mode)
601       mode = speex_lib_get_mode (modeID);
602
603    speex_init_header(&header, rate, 1, mode);
604    header.frames_per_packet=nframes;
605    header.vbr=vbr_enabled;
606    header.nb_channels = chan;
607
608    {
609       char *st_string="mono";
610       if (chan==2)
611          st_string="stereo";
612       if (!quiet)
613          fprintf (stderr, "Encoding %d Hz audio using %s mode (%s)\n", 
614                header.rate, mode->modeName, st_string);
615    }
616    /*fprintf (stderr, "Encoding %d Hz audio at %d bps using %s mode\n", 
617      header.rate, mode->bitrate, mode->modeName);*/
618
619    /*Initialize Speex encoder*/
620    st = speex_encoder_init(mode);
621
622    if (strcmp(outFile,"-")==0)
623    {
624 #if defined WIN32 || defined _WIN32
625       _setmode(_fileno(stdout), _O_BINARY);
626 #endif
627       fout=stdout;
628    }
629    else 
630    {
631       fout = fopen(outFile, "wb");
632       if (!fout)
633       {
634          perror(outFile);
635          exit(1);
636       }
637       close_out=1;
638    }
639
640    speex_encoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size);
641    speex_encoder_ctl(st, SPEEX_SET_COMPLEXITY, &complexity);
642    speex_encoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &rate);
643
644    if (quality >= 0)
645    {
646       if (vbr_enabled)
647       {
648          if (vbr_max>0)
649             speex_encoder_ctl(st, SPEEX_SET_VBR_MAX_BITRATE, &vbr_max);
650          speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_quality);
651       }
652       else
653          speex_encoder_ctl(st, SPEEX_SET_QUALITY, &quality);
654    }
655    if (bitrate)
656    {
657       if (quality >= 0 && vbr_enabled)
658          fprintf (stderr, "Warning: --bitrate option is overriding --quality\n");
659       speex_encoder_ctl(st, SPEEX_SET_BITRATE, &bitrate);
660    }
661    if (vbr_enabled)
662    {
663       tmp=1;
664       speex_encoder_ctl(st, SPEEX_SET_VBR, &tmp);
665    } else if (vad_enabled)
666    {
667       tmp=1;
668       speex_encoder_ctl(st, SPEEX_SET_VAD, &tmp);
669    }
670    if (dtx_enabled)
671       speex_encoder_ctl(st, SPEEX_SET_DTX, &tmp);
672    if (dtx_enabled && !(vbr_enabled || abr_enabled || vad_enabled))
673    {
674       fprintf (stderr, "Warning: --dtx is useless without --vad, --vbr or --abr\n");
675    } else if ((vbr_enabled || abr_enabled) && (vad_enabled))
676    {
677       fprintf (stderr, "Warning: --vad is already implied by --vbr or --abr\n");
678    }
679    if (with_skeleton) {
680       fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n");
681    }
682
683    if (abr_enabled)
684    {
685       speex_encoder_ctl(st, SPEEX_SET_ABR, &abr_enabled);
686    }
687
688    speex_encoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead);
689    
690    if (denoise_enabled || agc_enabled)
691    {
692       preprocess = speex_preprocess_state_init(frame_size, rate);
693       speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DENOISE, &denoise_enabled);
694       speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC, &agc_enabled);
695       lookahead += frame_size;
696    }
697
698    /* first packet should be the skeleton header. */
699
700    if (with_skeleton) {
701       add_fishead_packet(&so);
702       if ((ret = flush_ogg_stream_to_file(&so, fout))) {
703          fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n");
704          exit(1);
705       } else
706          bytes_written += ret;
707    }
708
709    /*Write header*/
710    {
711       int packet_size;
712       op.packet = (unsigned char *)speex_header_to_packet(&header, &packet_size);
713       op.bytes = packet_size;
714       op.b_o_s = 1;
715       op.e_o_s = 0;
716       op.granulepos = 0;
717       op.packetno = 0;
718       ogg_stream_packetin(&os, &op);
719       free(op.packet);
720
721       while((result = ogg_stream_flush(&os, &og)))
722       {
723          if(!result) break;
724          ret = oe_write_page(&og, fout);
725          if(ret != og.header_len + og.body_len)
726          {
727             fprintf (stderr,"Error: failed writing header to output stream\n");
728             exit(1);
729          }
730          else
731             bytes_written += ret;
732       }
733
734       op.packet = (unsigned char *)comments;
735       op.bytes = comments_length;
736       op.b_o_s = 0;
737       op.e_o_s = 0;
738       op.granulepos = 0;
739       op.packetno = 1;
740       ogg_stream_packetin(&os, &op);
741    }
742
743    /* fisbone packet should be write after all bos pages */
744    if (with_skeleton) {
745       add_fisbone_packet(&so, os.serialno, &header);
746       if ((ret = flush_ogg_stream_to_file(&so, fout))) {
747          fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n");
748          exit(1);
749       } else
750          bytes_written += ret;
751    }
752
753    /* writing the rest of the speex header packets */
754    while((result = ogg_stream_flush(&os, &og)))
755    {
756       if(!result) break;
757       ret = oe_write_page(&og, fout);
758       if(ret != og.header_len + og.body_len)
759       {
760          fprintf (stderr,"Error: failed writing header to output stream\n");
761          exit(1);
762       }
763       else
764          bytes_written += ret;
765    }
766
767    free(comments);
768
769    /* write the skeleton eos packet */
770    if (with_skeleton) {
771       add_eos_packet_to_stream(&so);
772       if ((ret = flush_ogg_stream_to_file(&so, fout))) {
773          fprintf (stderr,"Error: failed writing skeleton header to output stream\n");
774          exit(1);
775       } else
776          bytes_written += ret;
777    }
778
779
780    speex_bits_init(&bits);
781
782    if (!wave_input)
783    {
784       nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL);
785    } else {
786       nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size);
787    }
788    if (nb_samples==0)
789       eos=1;
790    total_samples += nb_samples;
791    nb_encoded = -lookahead;
792    /*Main encoding loop (one frame per iteration)*/
793    while (!eos || total_samples>nb_encoded)
794    {
795       id++;
796       /*Encode current frame*/
797       if (chan==2)
798          speex_encode_stereo_int(input, frame_size, &bits);
799
800       if (preprocess)
801          speex_preprocess(preprocess, input, NULL);
802
803       speex_encode_int(st, input, &bits);
804       
805       nb_encoded += frame_size;
806       if (print_bitrate) {
807          int tmp;
808          char ch=13;
809          speex_encoder_ctl(st, SPEEX_GET_BITRATE, &tmp);
810          fputc (ch, stderr);
811          cumul_bits += tmp;
812          enc_frames += 1;
813          if (!quiet)
814          {
815             if (vad_enabled || vbr_enabled || abr_enabled)
816                fprintf (stderr, "Bitrate is use: %d bps  (average %d bps)   ", tmp, (int)(cumul_bits/enc_frames));
817             else
818                fprintf (stderr, "Bitrate is use: %d bps     ", tmp);
819          }
820          
821       }
822
823       if (wave_input)
824       {
825          nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size);
826       } else {
827          nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL);
828       }
829       if (nb_samples==0)
830       {
831          eos=1;
832       }
833       if (eos && total_samples<=nb_encoded)
834          op.e_o_s = 1;
835       else
836          op.e_o_s = 0;
837       total_samples += nb_samples;
838
839       if ((id+1)%nframes!=0)
840          continue;
841       speex_bits_insert_terminator(&bits);
842       nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES);
843       speex_bits_reset(&bits);
844       op.packet = (unsigned char *)cbits;
845       op.bytes = nbBytes;
846       op.b_o_s = 0;
847       /*Is this redundent?*/
848       if (eos && total_samples<=nb_encoded)
849          op.e_o_s = 1;
850       else
851          op.e_o_s = 0;
852       op.granulepos = (id+1)*frame_size-lookahead;
853       if (op.granulepos>total_samples)
854          op.granulepos = total_samples;
855       /*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/
856       op.packetno = 2+id/nframes;
857       ogg_stream_packetin(&os, &op);
858
859       /*Write all new pages (most likely 0 or 1)*/
860       while (ogg_stream_pageout(&os,&og))
861       {
862          ret = oe_write_page(&og, fout);
863          if(ret != og.header_len + og.body_len)
864          {
865             fprintf (stderr,"Error: failed writing header to output stream\n");
866             exit(1);
867          }
868          else
869             bytes_written += ret;
870       }
871    }
872    if ((id+1)%nframes!=0)
873    {
874       while ((id+1)%nframes!=0)
875       {
876          id++;
877          speex_bits_pack(&bits, 15, 5);
878       }
879       nbBytes = speex_bits_write(&bits, cbits, MAX_FRAME_BYTES);
880       op.packet = (unsigned char *)cbits;
881       op.bytes = nbBytes;
882       op.b_o_s = 0;
883       op.e_o_s = 1;
884       op.granulepos = (id+1)*frame_size-lookahead;
885       if (op.granulepos>total_samples)
886          op.granulepos = total_samples;
887
888       op.packetno = 2+id/nframes;
889       ogg_stream_packetin(&os, &op);
890    }
891    /*Flush all pages left to be written*/
892    while (ogg_stream_flush(&os, &og))
893    {
894       ret = oe_write_page(&og, fout);
895       if(ret != og.header_len + og.body_len)
896       {
897          fprintf (stderr,"Error: failed writing header to output stream\n");
898          exit(1);
899       }
900       else
901          bytes_written += ret;
902    }
903
904    speex_encoder_destroy(st);
905    speex_bits_destroy(&bits);
906    ogg_stream_clear(&os);
907
908    if (close_in)
909       fclose(fin);
910    if (close_out)
911       fclose(fout);
912    return 0;
913 }
914
915 /*                 
916  Comments will be stored in the Vorbis style.            
917  It is describled in the "Structure" section of
918     http://www.xiph.org/ogg/vorbis/doc/v-comment.html
919
920 The comment header is decoded as follows:
921   1) [vendor_length] = read an unsigned integer of 32 bits
922   2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
923   3) [user_comment_list_length] = read an unsigned integer of 32 bits
924   4) iterate [user_comment_list_length] times {
925      5) [length] = read an unsigned integer of 32 bits
926      6) this iteration's user comment = read a UTF-8 vector as [length] octets
927      }
928   7) [framing_bit] = read a single bit as boolean
929   8) if ( [framing_bit]  unset or end of packet ) then ERROR
930   9) done.
931
932   If you have troubles, please write to ymnk@jcraft.com.
933  */
934
935 #define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
936                            ((buf[base+2]<<16)&0xff0000)| \
937                            ((buf[base+1]<<8)&0xff00)| \
938                             (buf[base]&0xff))
939 #define writeint(buf, base, val) do{ buf[base+3]=((val)>>24)&0xff; \
940                                      buf[base+2]=((val)>>16)&0xff; \
941                                      buf[base+1]=((val)>>8)&0xff; \
942                                      buf[base]=(val)&0xff; \
943                                  }while(0)
944
945 void comment_init(char **comments, int* length, char *vendor_string)
946 {
947   int vendor_length=strlen(vendor_string);
948   int user_comment_list_length=0;
949   int len=4+vendor_length+4;
950   char *p=(char*)malloc(len);
951   if(p==NULL){
952   }
953   writeint(p, 0, vendor_length);
954   memcpy(p+4, vendor_string, vendor_length);
955   writeint(p, 4+vendor_length, user_comment_list_length);
956   *length=len;
957   *comments=p;
958 }
959 void comment_add(char **comments, int* length, char *tag, char *val)
960 {
961   char* p=*comments;
962   int vendor_length=readint(p, 0);
963   int user_comment_list_length=readint(p, 4+vendor_length);
964   int tag_len=(tag?strlen(tag):0);
965   int val_len=strlen(val);
966   int len=(*length)+4+tag_len+val_len;
967
968   p=(char*)realloc(p, len);
969   if(p==NULL){
970   }
971
972   writeint(p, *length, tag_len+val_len);      /* length of comment */
973   if(tag) memcpy(p+*length+4, tag, tag_len);  /* comment */
974   memcpy(p+*length+4+tag_len, val, val_len);  /* comment */
975   writeint(p, 4+vendor_length, user_comment_list_length+1);
976
977   *comments=p;
978   *length=len;
979 }
980 #undef readint
981 #undef writeint