~ubuntu-branches/ubuntu/quantal/linphone/quantal

« back to all changes in this revision

Viewing changes to speex/src/speexenc.c

  • Committer: Bazaar Package Importer
  • Author(s): Samuel Mimram
  • Date: 2004-06-30 13:58:16 UTC
  • Revision ID: james.westby@ubuntu.com-20040630135816-wwx75gdlodkqbabb
Tags: upstream-0.12.2
ImportĀ upstreamĀ versionĀ 0.12.2

Show diffs side-by-side

added added

removed removed

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