Blame tools/celtenc.c

Packit 664db3
/* Copyright (C) 2002-2008 Jean-Marc Valin 
Packit 664db3
   File: celtenc.c
Packit 664db3
Packit 664db3
   Redistribution and use in source and binary forms, with or without
Packit 664db3
   modification, are permitted provided that the following conditions
Packit 664db3
   are met:
Packit 664db3
   
Packit 664db3
   - Redistributions of source code must retain the above copyright
Packit 664db3
   notice, this list of conditions and the following disclaimer.
Packit 664db3
   
Packit 664db3
   - Redistributions in binary form must reproduce the above copyright
Packit 664db3
   notice, this list of conditions and the following disclaimer in the
Packit 664db3
   documentation and/or other materials provided with the distribution.
Packit 664db3
   
Packit 664db3
   - Neither the name of the Xiph.org Foundation nor the names of its
Packit 664db3
   contributors may be used to endorse or promote products derived from
Packit 664db3
   this software without specific prior written permission.
Packit 664db3
   
Packit 664db3
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 664db3
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 664db3
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 664db3
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
Packit 664db3
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit 664db3
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit 664db3
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit 664db3
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit 664db3
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit 664db3
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit 664db3
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 664db3
*/
Packit 664db3
Packit 664db3
#ifdef HAVE_CONFIG_H
Packit 664db3
# include "config.h"
Packit 664db3
#endif
Packit 664db3
Packit 664db3
#include <stdio.h>
Packit 664db3
#if !defined WIN32 && !defined _WIN32
Packit 664db3
#include <unistd.h>
Packit 664db3
#endif
Packit 664db3
Packit 664db3
#ifdef HAVE_GETOPT_H
Packit 664db3
#include <getopt.h>
Packit 664db3
#endif
Packit 664db3
Packit 664db3
#ifndef HAVE_GETOPT_LONG
Packit 664db3
#include "getopt_win.h"
Packit 664db3
#endif
Packit 664db3
Packit 664db3
#include <stdlib.h>
Packit 664db3
#include <string.h>
Packit 664db3
#include <time.h>
Packit 664db3
Packit 664db3
#include "celt.h"
Packit 664db3
#include "celt_header.h"
Packit 664db3
#include <ogg/ogg.h>
Packit 664db3
#include "wav_io.h"
Packit 664db3
Packit 664db3
#if defined WIN32 || defined _WIN32
Packit 664db3
/* We need the following two to set stdout to binary */
Packit 664db3
#include <io.h>
Packit 664db3
#include <fcntl.h>
Packit 664db3
#endif
Packit 664db3
Packit 664db3
#include "skeleton.h"
Packit 664db3
Packit 664db3
Packit 664db3
void comment_init(char **comments, int* length, char *vendor_string);
Packit 664db3
void comment_add(char **comments, int* length, char *tag, char *val);
Packit 664db3
Packit 664db3
Packit 664db3
/*Write an Ogg page to a file pointer*/
Packit 664db3
int oe_write_page(ogg_page *page, FILE *fp)
Packit 664db3
{
Packit 664db3
   int written;
Packit 664db3
   written = fwrite(page->header,1,page->header_len, fp);
Packit 664db3
   written += fwrite(page->body,1,page->body_len, fp);
Packit 664db3
   
Packit 664db3
   return written;
Packit 664db3
}
Packit 664db3
Packit 664db3
#define MAX_FRAME_SIZE 2000
Packit 664db3
#define MAX_FRAME_BYTES 2000
Packit 664db3
Packit 664db3
/* Convert input audio bits, endians and channels */
Packit 664db3
static int read_samples(FILE *fin,int frame_size, int bits, int channels, int lsb, short * input, char *buff, celt_int32_t *size)
Packit 664db3
{   
Packit 664db3
   unsigned char in[MAX_FRAME_BYTES*2];
Packit 664db3
   int i;
Packit 664db3
   short *s;
Packit 664db3
   int nb_read;
Packit 664db3
Packit 664db3
   if (size && *size<=0)
Packit 664db3
   {
Packit 664db3
      return 0;
Packit 664db3
   }
Packit 664db3
   /*Read input audio*/
Packit 664db3
   if (size)
Packit 664db3
      *size -= bits/8*channels*frame_size;
Packit 664db3
   if (buff)
Packit 664db3
   {
Packit 664db3
      for (i=0;i<12;i++)
Packit 664db3
         in[i]=buff[i];
Packit 664db3
      nb_read = fread(in+12,1,bits/8*channels*frame_size-12, fin) + 12;
Packit 664db3
      if (size)
Packit 664db3
         *size += 12;
Packit 664db3
   } else {
Packit 664db3
      nb_read = fread(in,1,bits/8*channels* frame_size, fin);
Packit 664db3
   }
Packit 664db3
   nb_read /= bits/8*channels;
Packit 664db3
Packit 664db3
   /*fprintf (stderr, "%d\n", nb_read);*/
Packit 664db3
   if (nb_read==0)
Packit 664db3
      return 0;
Packit 664db3
Packit 664db3
   s=(short*)in;
Packit 664db3
   if(bits==8)
Packit 664db3
   {
Packit 664db3
      /* Convert 8->16 bits */
Packit 664db3
      for(i=frame_size*channels-1;i>=0;i--)
Packit 664db3
      {
Packit 664db3
         s[i]=(in[i]<<8)^0x8000;
Packit 664db3
      }
Packit 664db3
   } else
Packit 664db3
   {
Packit 664db3
      /* convert to our endian format */
Packit 664db3
      for(i=0;i
Packit 664db3
      {
Packit 664db3
         if(lsb) 
Packit 664db3
            s[i]=le_short(s[i]); 
Packit 664db3
         else
Packit 664db3
            s[i]=be_short(s[i]);
Packit 664db3
      }
Packit 664db3
   }
Packit 664db3
Packit 664db3
   /* FIXME: This is probably redundent now */
Packit 664db3
   /* copy to float input buffer */
Packit 664db3
   for (i=0;i
Packit 664db3
   {
Packit 664db3
      input[i]=(short)s[i];
Packit 664db3
   }
Packit 664db3
Packit 664db3
   for (i=nb_read*channels;i
Packit 664db3
   {
Packit 664db3
      input[i]=0;
Packit 664db3
   }
Packit 664db3
Packit 664db3
Packit 664db3
   return nb_read;
Packit 664db3
}
Packit 664db3
Packit 664db3
void add_fishead_packet (ogg_stream_state *os) {
Packit 664db3
Packit 664db3
   fishead_packet fp;
Packit 664db3
Packit 664db3
   memset(&fp, 0, sizeof(fp));
Packit 664db3
   fp.ptime_n = 0;
Packit 664db3
   fp.ptime_d = 1000;
Packit 664db3
   fp.btime_n = 0;
Packit 664db3
   fp.btime_d = 1000;
Packit 664db3
Packit 664db3
   add_fishead_to_stream(os, &fp);
Packit 664db3
}
Packit 664db3
Packit 664db3
/*
Packit 664db3
 * Adds the fishead packets in the skeleton output stream along with the e_o_s packet
Packit 664db3
 */
Packit 664db3
void add_fisbone_packet (ogg_stream_state *os, celt_int32_t serialno, CELT051Header *header) {
Packit 664db3
Packit 664db3
   fisbone_packet fp;
Packit 664db3
Packit 664db3
   memset(&fp, 0, sizeof(fp));
Packit 664db3
   fp.serial_no = serialno;
Packit 664db3
   fp.nr_header_packet = 2 + header->extra_headers;
Packit 664db3
   fp.granule_rate_n = header->sample_rate;
Packit 664db3
   fp.granule_rate_d = 1;
Packit 664db3
   fp.start_granule = 0;
Packit 664db3
   fp.preroll = 3;
Packit 664db3
   fp.granule_shift = 0;
Packit 664db3
Packit 664db3
   add_message_header_field(&fp, "Content-Type", "audio/x-celt");
Packit 664db3
Packit 664db3
   add_fisbone_to_stream(os, &fp);
Packit 664db3
}
Packit 664db3
Packit 664db3
void version(void)
Packit 664db3
{
Packit 664db3
   printf ("celtenc (CELT encoder)\n");
Packit 664db3
   printf ("Copyright (C) 2008 Jean-Marc Valin\n");
Packit 664db3
}
Packit 664db3
Packit 664db3
void version_short(void)
Packit 664db3
{
Packit 664db3
   printf ("celtenc (CELT encoder)\n");
Packit 664db3
   printf ("Copyright (C) 2008 Jean-Marc Valin\n");
Packit 664db3
}
Packit 664db3
Packit 664db3
void usage(void)
Packit 664db3
{
Packit 664db3
   printf ("Usage: celtenc [options] input_file output_file.oga\n");
Packit 664db3
   printf ("\n");
Packit 664db3
   printf ("Encodes input_file using CELT. It can read the WAV or raw files.\n");
Packit 664db3
   printf ("\n");
Packit 664db3
   printf ("input_file can be:\n");
Packit 664db3
   printf ("  filename.wav      wav file\n");
Packit 664db3
   printf ("  filename.*        Raw PCM file (any extension other than .wav)\n");
Packit 664db3
   printf ("  -                 stdin\n");
Packit 664db3
   printf ("\n");  
Packit 664db3
   printf ("output_file can be:\n");
Packit 664db3
   printf ("  filename.oga      compressed file\n");
Packit 664db3
   printf ("  -                 stdout\n");
Packit 664db3
   printf ("\n");  
Packit 664db3
   printf ("Options:\n");
Packit 664db3
   printf (" --bitrate n        Encoding bit-rate\n"); 
Packit 664db3
   printf (" --comp n           Encoding complexity (0-10)\n");
Packit 664db3
   printf (" --skeleton         Outputs ogg skeleton metadata (may cause incompatibilities)\n");
Packit 664db3
   printf (" --comment          Add the given string as an extra comment. This may be\n");
Packit 664db3
   printf ("                     used multiple times\n");
Packit 664db3
   printf (" --author           Author of this track\n");
Packit 664db3
   printf (" --title            Title for this track\n");
Packit 664db3
   printf (" -h, --help         This help\n"); 
Packit 664db3
   printf (" -v, --version      Version information\n"); 
Packit 664db3
   printf (" -V                 Verbose mode (show bit-rate)\n"); 
Packit 664db3
   printf ("Raw input options:\n");
Packit 664db3
   printf (" --rate n           Sampling rate for raw input\n"); 
Packit 664db3
   printf (" --mono             Consider raw input as mono\n"); 
Packit 664db3
   printf (" --stereo           Consider raw input as stereo\n"); 
Packit 664db3
   printf (" --le               Raw input is little-endian\n"); 
Packit 664db3
   printf (" --be               Raw input is big-endian\n"); 
Packit 664db3
   printf (" --8bit             Raw input is 8-bit unsigned\n"); 
Packit 664db3
   printf (" --16bit            Raw input is 16-bit signed\n"); 
Packit 664db3
   printf ("Default raw PCM input is 16-bit, little-endian, mono\n"); 
Packit 664db3
}
Packit 664db3
Packit 664db3
Packit 664db3
int main(int argc, char **argv)
Packit 664db3
{
Packit 664db3
   int nb_samples, total_samples=0, nb_encoded;
Packit 664db3
   int c;
Packit 664db3
   int option_index = 0;
Packit 664db3
   char *inFile, *outFile;
Packit 664db3
   FILE *fin, *fout;
Packit 664db3
   short input[MAX_FRAME_SIZE];
Packit 664db3
   celt_int32_t frame_size;
Packit 664db3
   int quiet=0;
Packit 664db3
   int nbBytes;
Packit 664db3
   CELTMode *mode;
Packit 664db3
   void *st;
Packit 664db3
   unsigned char bits[MAX_FRAME_BYTES];
Packit 664db3
   int with_skeleton = 0;
Packit 664db3
   struct option long_options[] =
Packit 664db3
   {
Packit 664db3
      {"bitrate", required_argument, NULL, 0},
Packit 664db3
      {"comp", required_argument, NULL, 0},
Packit 664db3
      {"skeleton",no_argument,NULL, 0},
Packit 664db3
      {"help", no_argument, NULL, 0},
Packit 664db3
      {"quiet", no_argument, NULL, 0},
Packit 664db3
      {"le", no_argument, NULL, 0},
Packit 664db3
      {"be", no_argument, NULL, 0},
Packit 664db3
      {"8bit", no_argument, NULL, 0},
Packit 664db3
      {"16bit", no_argument, NULL, 0},
Packit 664db3
      {"mono", no_argument, NULL, 0},
Packit 664db3
      {"stereo", no_argument, NULL, 0},
Packit 664db3
      {"rate", required_argument, NULL, 0},
Packit 664db3
      {"version", no_argument, NULL, 0},
Packit 664db3
      {"version-short", no_argument, NULL, 0},
Packit 664db3
      {"comment", required_argument, NULL, 0},
Packit 664db3
      {"author", required_argument, NULL, 0},
Packit 664db3
      {"title", required_argument, NULL, 0},
Packit 664db3
      {0, 0, 0, 0}
Packit 664db3
   };
Packit 664db3
   int print_bitrate=0;
Packit 664db3
   celt_int32_t rate=44100;
Packit 664db3
   celt_int32_t size;
Packit 664db3
   int chan=1;
Packit 664db3
   int fmt=16;
Packit 664db3
   int lsb=1;
Packit 664db3
   ogg_stream_state os;
Packit 664db3
   ogg_stream_state so; /* ogg stream for skeleton bitstream */
Packit 664db3
   ogg_page 		 og;
Packit 664db3
   ogg_packet 		 op;
Packit 664db3
   int bytes_written=0, ret, result;
Packit 664db3
   int id=-1;
Packit 664db3
   CELT051Header header;
Packit 664db3
   char vendor_string[64];
Packit 664db3
   char *comments;
Packit 664db3
   int comments_length;
Packit 664db3
   int close_in=0, close_out=0;
Packit 664db3
   int eos=0;
Packit 664db3
   celt_int32_t bitrate=-1;
Packit 664db3
   char first_bytes[12];
Packit 664db3
   int wave_input=0;
Packit 664db3
   celt_int32_t lookahead = 0;
Packit 664db3
   int bytes_per_packet=48;
Packit 664db3
   int complexity=-127;
Packit 664db3
   
Packit 664db3
   snprintf(vendor_string, sizeof(vendor_string), "Encoded with CELT\n");
Packit 664db3
   
Packit 664db3
   comment_init(&comments, &comments_length, vendor_string);
Packit 664db3
Packit 664db3
   /*Process command-line options*/
Packit 664db3
   while(1)
Packit 664db3
   {
Packit 664db3
      c = getopt_long (argc, argv, "hvV",
Packit 664db3
                       long_options, &option_index);
Packit 664db3
      if (c==-1)
Packit 664db3
         break;
Packit 664db3
      
Packit 664db3
      switch(c)
Packit 664db3
      {
Packit 664db3
      case 0:
Packit 664db3
         if (strcmp(long_options[option_index].name,"bitrate")==0)
Packit 664db3
         {
Packit 664db3
            bitrate = atoi (optarg);
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"skeleton")==0)
Packit 664db3
         {
Packit 664db3
            with_skeleton=1;
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"help")==0)
Packit 664db3
         {
Packit 664db3
            usage();
Packit 664db3
            exit(0);
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"quiet")==0)
Packit 664db3
         {
Packit 664db3
            quiet = 1;
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"version")==0)
Packit 664db3
         {
Packit 664db3
            version();
Packit 664db3
            exit(0);
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"version-short")==0)
Packit 664db3
         {
Packit 664db3
            version_short();
Packit 664db3
            exit(0);
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"le")==0)
Packit 664db3
         {
Packit 664db3
            lsb=1;
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"be")==0)
Packit 664db3
         {
Packit 664db3
            lsb=0;
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"8bit")==0)
Packit 664db3
         {
Packit 664db3
            fmt=8;
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"16bit")==0)
Packit 664db3
         {
Packit 664db3
            fmt=16;
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"stereo")==0)
Packit 664db3
         {
Packit 664db3
            chan=2;
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"mono")==0)
Packit 664db3
         {
Packit 664db3
            chan=1;
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"rate")==0)
Packit 664db3
         {
Packit 664db3
            rate=atoi (optarg);
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"comp")==0)
Packit 664db3
         {
Packit 664db3
            complexity=atoi (optarg);
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"comment")==0)
Packit 664db3
         {
Packit 664db3
	   if (!strchr(optarg, '='))
Packit 664db3
	   {
Packit 664db3
	     fprintf (stderr, "Invalid comment: %s\n", optarg);
Packit 664db3
	     fprintf (stderr, "Comments must be of the form name=value\n");
Packit 664db3
	     exit(1);
Packit 664db3
	   }
Packit 664db3
           comment_add(&comments, &comments_length, NULL, optarg); 
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"author")==0)
Packit 664db3
         {
Packit 664db3
           comment_add(&comments, &comments_length, "author=", optarg); 
Packit 664db3
         } else if (strcmp(long_options[option_index].name,"title")==0)
Packit 664db3
         {
Packit 664db3
           comment_add(&comments, &comments_length, "title=", optarg); 
Packit 664db3
         }
Packit 664db3
Packit 664db3
         break;
Packit 664db3
      case 'h':
Packit 664db3
         usage();
Packit 664db3
         exit(0);
Packit 664db3
         break;
Packit 664db3
      case 'v':
Packit 664db3
         version();
Packit 664db3
         exit(0);
Packit 664db3
         break;
Packit 664db3
      case 'V':
Packit 664db3
         print_bitrate=1;
Packit 664db3
         break;
Packit 664db3
      case '?':
Packit 664db3
         usage();
Packit 664db3
         exit(1);
Packit 664db3
         break;
Packit 664db3
      }
Packit 664db3
   }
Packit 664db3
Packit 664db3
   fprintf(stderr,"\nWARNING: This encoder is a CELT *PRERELEASE*. It produces streams that are\n"
Packit 664db3
           "         not decodable by ANY OTHER VERSION.  These streams will NOT be\n"
Packit 664db3
           "         supported or decodable by any future CELT release.\n\n");
Packit 664db3
Packit 664db3
   if (argc-optind!=2)
Packit 664db3
   {
Packit 664db3
      usage();
Packit 664db3
      exit(1);
Packit 664db3
   }
Packit 664db3
   inFile=argv[optind];
Packit 664db3
   outFile=argv[optind+1];
Packit 664db3
Packit 664db3
   /*Initialize Ogg stream struct*/
Packit 664db3
   srand(time(NULL));
Packit 664db3
   if (ogg_stream_init(&os, rand())==-1)
Packit 664db3
   {
Packit 664db3
      fprintf(stderr,"Error: stream init failed\n");
Packit 664db3
      exit(1);
Packit 664db3
   }
Packit 664db3
   if (with_skeleton && ogg_stream_init(&so, rand())==-1)
Packit 664db3
   {
Packit 664db3
      fprintf(stderr,"Error: stream init failed\n");
Packit 664db3
      exit(1);
Packit 664db3
   }
Packit 664db3
Packit 664db3
   if (strcmp(inFile, "-")==0)
Packit 664db3
   {
Packit 664db3
#if defined WIN32 || defined _WIN32
Packit 664db3
         _setmode(_fileno(stdin), _O_BINARY);
Packit 664db3
#elif defined OS2
Packit 664db3
         _fsetmode(stdin,"b");
Packit 664db3
#endif
Packit 664db3
      fin=stdin;
Packit 664db3
   }
Packit 664db3
   else 
Packit 664db3
   {
Packit 664db3
      fin = fopen(inFile, "rb");
Packit 664db3
      if (!fin)
Packit 664db3
      {
Packit 664db3
         perror(inFile);
Packit 664db3
         exit(1);
Packit 664db3
      }
Packit 664db3
      close_in=1;
Packit 664db3
   }
Packit 664db3
Packit 664db3
   {
Packit 664db3
      fread(first_bytes, 1, 12, fin);
Packit 664db3
      if (strncmp(first_bytes,"RIFF",4)==0 && strncmp(first_bytes,"RIFF",4)==0)
Packit 664db3
      {
Packit 664db3
         if (read_wav_header(fin, &rate, &chan, &fmt, &size)==-1)
Packit 664db3
            exit(1);
Packit 664db3
         wave_input=1;
Packit 664db3
         lsb=1; /* CHECK: exists big-endian .wav ?? */
Packit 664db3
      }
Packit 664db3
   }
Packit 664db3
Packit 664db3
   if (chan == 1)
Packit 664db3
   {
Packit 664db3
      if (bitrate < 0)
Packit 664db3
         bitrate = 64;
Packit 664db3
      if (bitrate < 32)
Packit 664db3
         bitrate = 32;
Packit 664db3
      if (bitrate > 110)
Packit 664db3
         bitrate = 110;
Packit 664db3
   }
Packit 664db3
   else if (chan == 2)
Packit 664db3
   {
Packit 664db3
      if (bitrate < 0)
Packit 664db3
         bitrate = 128;
Packit 664db3
      if (bitrate < 64)
Packit 664db3
         bitrate = 64;
Packit 664db3
      if (bitrate > 150)
Packit 664db3
         bitrate = 150;
Packit 664db3
   } else {
Packit 664db3
      fprintf (stderr, "Only mono and stereo are supported\n");
Packit 664db3
      return 1;
Packit 664db3
   }
Packit 664db3
Packit 664db3
   mode = celt051_mode_create(rate, chan, 256, NULL);
Packit 664db3
   if (!mode)
Packit 664db3
      return 1;
Packit 664db3
   celt051_mode_info(mode, CELT_GET_FRAME_SIZE, &frame_size);
Packit 664db3
   
Packit 664db3
   bytes_per_packet = (bitrate*1000*frame_size/rate+4)/8;
Packit 664db3
   
Packit 664db3
   celt051_header_init(&header, mode);
Packit 664db3
   header.nb_channels = chan;
Packit 664db3
Packit 664db3
   {
Packit 664db3
      char *st_string="mono";
Packit 664db3
      if (chan==2)
Packit 664db3
         st_string="stereo";
Packit 664db3
      if (!quiet)
Packit 664db3
         fprintf (stderr, "Encoding %d Hz audio using %s (%d bytes per packet)\n", 
Packit 664db3
               header.sample_rate, st_string, bytes_per_packet);
Packit 664db3
   }
Packit 664db3
   /*fprintf (stderr, "Encoding %d Hz audio at %d bps using %s mode\n", 
Packit 664db3
     header.rate, mode->bitrate, mode->modeName);*/
Packit 664db3
Packit 664db3
   /*Initialize CELT encoder*/
Packit 664db3
   st = celt051_encoder_create(mode);
Packit 664db3
Packit 664db3
   if (complexity!=-127) {
Packit 664db3
     if (celt051_encoder_ctl(st, CELT_SET_COMPLEXITY(complexity)) != CELT_OK)
Packit 664db3
     {
Packit 664db3
        fprintf (stderr, "Only complexity 0 through 10 is supported\n");
Packit 664db3
        return 1;
Packit 664db3
     }
Packit 664db3
   }
Packit 664db3
Packit 664db3
   if (strcmp(outFile,"-")==0)
Packit 664db3
   {
Packit 664db3
#if defined WIN32 || defined _WIN32
Packit 664db3
      _setmode(_fileno(stdout), _O_BINARY);
Packit 664db3
#endif
Packit 664db3
      fout=stdout;
Packit 664db3
   }
Packit 664db3
   else 
Packit 664db3
   {
Packit 664db3
      fout = fopen(outFile, "wb");
Packit 664db3
      if (!fout)
Packit 664db3
      {
Packit 664db3
         perror(outFile);
Packit 664db3
         exit(1);
Packit 664db3
      }
Packit 664db3
      close_out=1;
Packit 664db3
   }
Packit 664db3
Packit 664db3
   if (with_skeleton) {
Packit 664db3
      fprintf (stderr, "Warning: Enabling skeleton output may cause some decoders to fail.\n");
Packit 664db3
   }
Packit 664db3
Packit 664db3
   /* first packet should be the skeleton header. */
Packit 664db3
   if (with_skeleton) {
Packit 664db3
      add_fishead_packet(&so);
Packit 664db3
      if ((ret = flush_ogg_stream_to_file(&so, fout))) {
Packit 664db3
	 fprintf (stderr,"Error: failed skeleton (fishead) header to output stream\n");
Packit 664db3
         exit(1);
Packit 664db3
      } else
Packit 664db3
	 bytes_written += ret;
Packit 664db3
   }
Packit 664db3
Packit 664db3
   /*Write header*/
Packit 664db3
   {
Packit 664db3
      unsigned char header_data[100];
Packit 664db3
      int packet_size = celt051_header_to_packet(&header, header_data, 100);
Packit 664db3
      op.packet = header_data;
Packit 664db3
      op.bytes = packet_size;
Packit 664db3
      op.b_o_s = 1;
Packit 664db3
      op.e_o_s = 0;
Packit 664db3
      op.granulepos = 0;
Packit 664db3
      op.packetno = 0;
Packit 664db3
      ogg_stream_packetin(&os, &op);
Packit 664db3
Packit 664db3
      while((result = ogg_stream_flush(&os, &og)))
Packit 664db3
      {
Packit 664db3
         if(!result) break;
Packit 664db3
         ret = oe_write_page(&og, fout);
Packit 664db3
         if(ret != og.header_len + og.body_len)
Packit 664db3
         {
Packit 664db3
            fprintf (stderr,"Error: failed writing header to output stream\n");
Packit 664db3
            exit(1);
Packit 664db3
         }
Packit 664db3
         else
Packit 664db3
            bytes_written += ret;
Packit 664db3
      }
Packit 664db3
Packit 664db3
      op.packet = (unsigned char *)comments;
Packit 664db3
      op.bytes = comments_length;
Packit 664db3
      op.b_o_s = 0;
Packit 664db3
      op.e_o_s = 0;
Packit 664db3
      op.granulepos = 0;
Packit 664db3
      op.packetno = 1;
Packit 664db3
      ogg_stream_packetin(&os, &op);
Packit 664db3
   }
Packit 664db3
Packit 664db3
   /* fisbone packet should be write after all bos pages */
Packit 664db3
   if (with_skeleton) {
Packit 664db3
      add_fisbone_packet(&so, os.serialno, &header);
Packit 664db3
      if ((ret = flush_ogg_stream_to_file(&so, fout))) {
Packit 664db3
	 fprintf (stderr,"Error: failed writing skeleton (fisbone )header to output stream\n");
Packit 664db3
         exit(1);
Packit 664db3
      } else
Packit 664db3
	 bytes_written += ret;
Packit 664db3
   }
Packit 664db3
Packit 664db3
   /* writing the rest of the celt header packets */
Packit 664db3
   while((result = ogg_stream_flush(&os, &og)))
Packit 664db3
   {
Packit 664db3
      if(!result) break;
Packit 664db3
      ret = oe_write_page(&og, fout);
Packit 664db3
      if(ret != og.header_len + og.body_len)
Packit 664db3
      {
Packit 664db3
         fprintf (stderr,"Error: failed writing header to output stream\n");
Packit 664db3
         exit(1);
Packit 664db3
      }
Packit 664db3
      else
Packit 664db3
         bytes_written += ret;
Packit 664db3
   }
Packit 664db3
Packit 664db3
   free(comments);
Packit 664db3
Packit 664db3
   /* write the skeleton eos packet */
Packit 664db3
   if (with_skeleton) {
Packit 664db3
      add_eos_packet_to_stream(&so);
Packit 664db3
      if ((ret = flush_ogg_stream_to_file(&so, fout))) {
Packit 664db3
         fprintf (stderr,"Error: failed writing skeleton header to output stream\n");
Packit 664db3
         exit(1);
Packit 664db3
      } else
Packit 664db3
	 bytes_written += ret;
Packit 664db3
   }
Packit 664db3
Packit 664db3
Packit 664db3
   if (!wave_input)
Packit 664db3
   {
Packit 664db3
      nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, first_bytes, NULL);
Packit 664db3
   } else {
Packit 664db3
      nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size);
Packit 664db3
   }
Packit 664db3
   if (nb_samples==0)
Packit 664db3
      eos=1;
Packit 664db3
   total_samples += nb_samples;
Packit 664db3
   nb_encoded = -lookahead;
Packit 664db3
   /*Main encoding loop (one frame per iteration)*/
Packit 664db3
   while (!eos || total_samples>nb_encoded)
Packit 664db3
   {
Packit 664db3
      id++;
Packit 664db3
      /*Encode current frame*/
Packit 664db3
Packit 664db3
      nbBytes = celt051_encode(st, input, NULL, bits, bytes_per_packet);
Packit 664db3
      if (nbBytes<0)
Packit 664db3
      {
Packit 664db3
         fprintf(stderr, "Got error %d while encoding. Aborting.\n", nbBytes);
Packit 664db3
         break;
Packit 664db3
      }
Packit 664db3
      nb_encoded += frame_size;
Packit 664db3
Packit 664db3
      if (wave_input)
Packit 664db3
      {
Packit 664db3
         nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, &size);
Packit 664db3
      } else {
Packit 664db3
         nb_samples = read_samples(fin,frame_size,fmt,chan,lsb,input, NULL, NULL);
Packit 664db3
      }
Packit 664db3
      if (nb_samples==0)
Packit 664db3
      {
Packit 664db3
         eos=1;
Packit 664db3
      }
Packit 664db3
      if (eos && total_samples<=nb_encoded)
Packit 664db3
         op.e_o_s = 1;
Packit 664db3
      else
Packit 664db3
         op.e_o_s = 0;
Packit 664db3
      total_samples += nb_samples;
Packit 664db3
Packit 664db3
      op.packet = (unsigned char *)bits;
Packit 664db3
      op.bytes = nbBytes;
Packit 664db3
      op.b_o_s = 0;
Packit 664db3
      /*Is this redundent?*/
Packit 664db3
      if (eos && total_samples<=nb_encoded)
Packit 664db3
         op.e_o_s = 1;
Packit 664db3
      else
Packit 664db3
         op.e_o_s = 0;
Packit 664db3
      op.granulepos = (id+1)*frame_size-lookahead;
Packit 664db3
      if (op.granulepos>total_samples)
Packit 664db3
         op.granulepos = total_samples;
Packit 664db3
      /*printf ("granulepos: %d %d %d %d %d %d\n", (int)op.granulepos, id, nframes, lookahead, 5, 6);*/
Packit 664db3
      op.packetno = 2+id;
Packit 664db3
      ogg_stream_packetin(&os, &op);
Packit 664db3
Packit 664db3
      /*Write all new pages (most likely 0 or 1)*/
Packit 664db3
      while (ogg_stream_pageout(&os,&og))
Packit 664db3
      {
Packit 664db3
         ret = oe_write_page(&og, fout);
Packit 664db3
         if(ret != og.header_len + og.body_len)
Packit 664db3
         {
Packit 664db3
            fprintf (stderr,"Error: failed writing header to output stream\n");
Packit 664db3
            exit(1);
Packit 664db3
         }
Packit 664db3
         else
Packit 664db3
            bytes_written += ret;
Packit 664db3
      }
Packit 664db3
   }
Packit 664db3
   /*Flush all pages left to be written*/
Packit 664db3
   while (ogg_stream_flush(&os, &og))
Packit 664db3
   {
Packit 664db3
      ret = oe_write_page(&og, fout);
Packit 664db3
      if(ret != og.header_len + og.body_len)
Packit 664db3
      {
Packit 664db3
         fprintf (stderr,"Error: failed writing header to output stream\n");
Packit 664db3
         exit(1);
Packit 664db3
      }
Packit 664db3
      else
Packit 664db3
         bytes_written += ret;
Packit 664db3
   }
Packit 664db3
Packit 664db3
   celt051_encoder_destroy(st);
Packit 664db3
   celt051_mode_destroy(mode);
Packit 664db3
   ogg_stream_clear(&os);
Packit 664db3
Packit 664db3
   if (close_in)
Packit 664db3
      fclose(fin);
Packit 664db3
   if (close_out)
Packit 664db3
      fclose(fout);
Packit 664db3
   return 0;
Packit 664db3
}
Packit 664db3
Packit 664db3
/*                 
Packit 664db3
 Comments will be stored in the Vorbis style.            
Packit 664db3
 It is describled in the "Structure" section of
Packit 664db3
    http://www.xiph.org/ogg/vorbis/doc/v-comment.html
Packit 664db3
Packit 664db3
The comment header is decoded as follows:
Packit 664db3
  1) [vendor_length] = read an unsigned integer of 32 bits
Packit 664db3
  2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
Packit 664db3
  3) [user_comment_list_length] = read an unsigned integer of 32 bits
Packit 664db3
  4) iterate [user_comment_list_length] times {
Packit 664db3
     5) [length] = read an unsigned integer of 32 bits
Packit 664db3
     6) this iteration's user comment = read a UTF-8 vector as [length] octets
Packit 664db3
     }
Packit 664db3
  7) [framing_bit] = read a single bit as boolean
Packit 664db3
  8) if ( [framing_bit]  unset or end of packet ) then ERROR
Packit 664db3
  9) done.
Packit 664db3
Packit 664db3
  If you have troubles, please write to ymnk@jcraft.com.
Packit 664db3
 */
Packit 664db3
Packit 664db3
#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
Packit 664db3
                           ((buf[base+2]<<16)&0xff0000)| \
Packit 664db3
                           ((buf[base+1]<<8)&0xff00)| \
Packit 664db3
  	           	    (buf[base]&0xff))
Packit 664db3
#define writeint(buf, base, val) do{ buf[base+3]=((val)>>24)&0xff; \
Packit 664db3
                                     buf[base+2]=((val)>>16)&0xff; \
Packit 664db3
                                     buf[base+1]=((val)>>8)&0xff; \
Packit 664db3
                                     buf[base]=(val)&0xff; \
Packit 664db3
                                 }while(0)
Packit 664db3
Packit 664db3
void comment_init(char **comments, int* length, char *vendor_string)
Packit 664db3
{
Packit 664db3
  int vendor_length=strlen(vendor_string);
Packit 664db3
  int user_comment_list_length=0;
Packit 664db3
  int len=4+vendor_length+4;
Packit 664db3
  char *p=(char*)malloc(len);
Packit 664db3
  if(p==NULL){
Packit 664db3
     fprintf (stderr, "malloc failed in comment_init()\n");
Packit 664db3
     exit(1);
Packit 664db3
  }
Packit 664db3
  writeint(p, 0, vendor_length);
Packit 664db3
  memcpy(p+4, vendor_string, vendor_length);
Packit 664db3
  writeint(p, 4+vendor_length, user_comment_list_length);
Packit 664db3
  *length=len;
Packit 664db3
  *comments=p;
Packit 664db3
}
Packit 664db3
void comment_add(char **comments, int* length, char *tag, char *val)
Packit 664db3
{
Packit 664db3
  char* p=*comments;
Packit 664db3
  int vendor_length=readint(p, 0);
Packit 664db3
  int user_comment_list_length=readint(p, 4+vendor_length);
Packit 664db3
  int tag_len=(tag?strlen(tag):0);
Packit 664db3
  int val_len=strlen(val);
Packit 664db3
  int len=(*length)+4+tag_len+val_len;
Packit 664db3
Packit 664db3
  p=(char*)realloc(p, len);
Packit 664db3
  if(p==NULL){
Packit 664db3
     fprintf (stderr, "realloc failed in comment_add()\n");
Packit 664db3
     exit(1);
Packit 664db3
  }
Packit 664db3
Packit 664db3
  writeint(p, *length, tag_len+val_len);      /* length of comment */
Packit 664db3
  if(tag) memcpy(p+*length+4, tag, tag_len);  /* comment */
Packit 664db3
  memcpy(p+*length+4+tag_len, val, val_len);  /* comment */
Packit 664db3
  writeint(p, 4+vendor_length, user_comment_list_length+1);
Packit 664db3
Packit 664db3
  *comments=p;
Packit 664db3
  *length=len;
Packit 664db3
}
Packit 664db3
#undef readint
Packit 664db3
#undef writeint