speexenc.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:26k
源码类别:

Windows CE

开发平台:

C/C++

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