Blame examples/encoder_example.c

Packit 06404a
/********************************************************************
Packit 06404a
 *                                                                  *
Packit 06404a
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
Packit 06404a
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
Packit 06404a
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
Packit 06404a
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
Packit 06404a
 *                                                                  *
Packit 06404a
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
Packit 06404a
 * by the Xiph.Org Foundation http://www.xiph.org/                  *
Packit 06404a
 *                                                                  *
Packit 06404a
 ********************************************************************
Packit 06404a
Packit 06404a
 function: simple example encoder
Packit 06404a
 last mod: $Id: encoder_example.c 16946 2010-03-03 16:12:40Z xiphmont $
Packit 06404a
Packit 06404a
 ********************************************************************/
Packit 06404a
Packit 06404a
/* takes a stereo 16bit 44.1kHz WAV file from stdin and encodes it into
Packit 06404a
   a Vorbis bitstream */
Packit 06404a
Packit 06404a
/* Note that this is POSIX, not ANSI, code */
Packit 06404a
Packit 06404a
#include <stdio.h>
Packit 06404a
#include <stdlib.h>
Packit 06404a
#include <string.h>
Packit 06404a
#include <time.h>
Packit 06404a
#include <math.h>
Packit 06404a
#include <vorbis/vorbisenc.h>
Packit 06404a
Packit 06404a
#ifdef _WIN32 /* We need the following two to set stdin/stdout to binary */
Packit 06404a
#include <io.h>
Packit 06404a
#include <fcntl.h>
Packit 06404a
#endif
Packit 06404a
Packit 06404a
#if defined(__MACOS__) && defined(__MWERKS__)
Packit 06404a
#include <console.h>      /* CodeWarrior's Mac "command-line" support */
Packit 06404a
#endif
Packit 06404a
Packit 06404a
#define READ 1024
Packit 06404a
signed char readbuffer[READ*4+44]; /* out of the data segment, not the stack */
Packit 06404a
Packit 06404a
int main(){
Packit 06404a
  ogg_stream_state os; /* take physical pages, weld into a logical
Packit 06404a
                          stream of packets */
Packit 06404a
  ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
Packit 06404a
  ogg_packet       op; /* one raw packet of data for decode */
Packit 06404a
Packit 06404a
  vorbis_info      vi; /* struct that stores all the static vorbis bitstream
Packit 06404a
                          settings */
Packit 06404a
  vorbis_comment   vc; /* struct that stores all the user comments */
Packit 06404a
Packit 06404a
  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
Packit 06404a
  vorbis_block     vb; /* local working space for packet->PCM decode */
Packit 06404a
Packit 06404a
  int eos=0,ret;
Packit 06404a
  int i, founddata;
Packit 06404a
Packit 06404a
#if defined(macintosh) && defined(__MWERKS__)
Packit 06404a
  int argc = 0;
Packit 06404a
  char **argv = NULL;
Packit 06404a
  argc = ccommand(&argv); /* get a "command line" from the Mac user */
Packit 06404a
                          /* this also lets the user set stdin and stdout */
Packit 06404a
#endif
Packit 06404a
Packit 06404a
  /* we cheat on the WAV header; we just bypass 44 bytes (simplest WAV
Packit 06404a
     header is 44 bytes) and assume that the data is 44.1khz, stereo, 16 bit
Packit 06404a
     little endian pcm samples. This is just an example, after all. */
Packit 06404a
Packit 06404a
#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
Packit 06404a
  /* if we were reading/writing a file, it would also need to in
Packit 06404a
     binary mode, eg, fopen("file.wav","wb"); */
Packit 06404a
  /* Beware the evil ifdef. We avoid these where we can, but this one we
Packit 06404a
     cannot. Don't add any more, you'll probably go to hell if you do. */
Packit 06404a
  _setmode( _fileno( stdin ), _O_BINARY );
Packit 06404a
  _setmode( _fileno( stdout ), _O_BINARY );
Packit 06404a
#endif
Packit 06404a
Packit 06404a
Packit 06404a
  /* we cheat on the WAV header; we just bypass the header and never
Packit 06404a
     verify that it matches 16bit/stereo/44.1kHz.  This is just an
Packit 06404a
     example, after all. */
Packit 06404a
Packit 06404a
  readbuffer[0] = '\0';
Packit 06404a
  for (i=0, founddata=0; i<30 && ! feof(stdin) && ! ferror(stdin); i++)
Packit 06404a
  {
Packit 06404a
    fread(readbuffer,1,2,stdin);
Packit 06404a
Packit 06404a
    if ( ! strncmp((char*)readbuffer, "da", 2) ){
Packit 06404a
      founddata = 1;
Packit 06404a
      fread(readbuffer,1,6,stdin);
Packit 06404a
      break;
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /********** Encode setup ************/
Packit 06404a
Packit 06404a
  vorbis_info_init(&vi;;
Packit 06404a
Packit 06404a
  /* choose an encoding mode.  A few possibilities commented out, one
Packit 06404a
     actually used: */
Packit 06404a
Packit 06404a
  /*********************************************************************
Packit 06404a
   Encoding using a VBR quality mode.  The usable range is -.1
Packit 06404a
   (lowest quality, smallest file) to 1. (highest quality, largest file).
Packit 06404a
   Example quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR
Packit 06404a
Packit 06404a
   ret = vorbis_encode_init_vbr(&vi,2,44100,.4);
Packit 06404a
Packit 06404a
   ---------------------------------------------------------------------
Packit 06404a
Packit 06404a
   Encoding using an average bitrate mode (ABR).
Packit 06404a
   example: 44kHz stereo coupled, average 128kbps VBR
Packit 06404a
Packit 06404a
   ret = vorbis_encode_init(&vi,2,44100,-1,128000,-1);
Packit 06404a
Packit 06404a
   ---------------------------------------------------------------------
Packit 06404a
Packit 06404a
   Encode using a quality mode, but select that quality mode by asking for
Packit 06404a
   an approximate bitrate.  This is not ABR, it is true VBR, but selected
Packit 06404a
   using the bitrate interface, and then turning bitrate management off:
Packit 06404a
Packit 06404a
   ret = ( vorbis_encode_setup_managed(&vi,2,44100,-1,128000,-1) ||
Packit 06404a
           vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE2_SET,NULL) ||
Packit 06404a
           vorbis_encode_setup_init(&vi));
Packit 06404a
Packit 06404a
   *********************************************************************/
Packit 06404a
Packit 06404a
  ret=vorbis_encode_init_vbr(&vi,2,44100,0.1);
Packit 06404a
Packit 06404a
  /* do not continue if setup failed; this can happen if we ask for a
Packit 06404a
     mode that libVorbis does not support (eg, too low a bitrate, etc,
Packit 06404a
     will return 'OV_EIMPL') */
Packit 06404a
Packit 06404a
  if(ret)exit(1);
Packit 06404a
Packit 06404a
  /* add a comment */
Packit 06404a
  vorbis_comment_init(&vc);
Packit 06404a
  vorbis_comment_add_tag(&vc,"ENCODER","encoder_example.c");
Packit 06404a
Packit 06404a
  /* set up the analysis state and auxiliary encoding storage */
Packit 06404a
  vorbis_analysis_init(&vd,&vi;;
Packit 06404a
  vorbis_block_init(&vd,&vb;;
Packit 06404a
Packit 06404a
  /* set up our packet->stream encoder */
Packit 06404a
  /* pick a random serial number; that way we can more likely build
Packit 06404a
     chained streams just by concatenation */
Packit 06404a
  srand(time(NULL));
Packit 06404a
  ogg_stream_init(&os,rand());
Packit 06404a
Packit 06404a
  /* Vorbis streams begin with three headers; the initial header (with
Packit 06404a
     most of the codec setup parameters) which is mandated by the Ogg
Packit 06404a
     bitstream spec.  The second header holds any comment fields.  The
Packit 06404a
     third header holds the bitstream codebook.  We merely need to
Packit 06404a
     make the headers, then pass them to libvorbis one at a time;
Packit 06404a
     libvorbis handles the additional Ogg bitstream constraints */
Packit 06404a
Packit 06404a
  {
Packit 06404a
    ogg_packet header;
Packit 06404a
    ogg_packet header_comm;
Packit 06404a
    ogg_packet header_code;
Packit 06404a
Packit 06404a
    vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
Packit 06404a
    ogg_stream_packetin(&os,&header); /* automatically placed in its own
Packit 06404a
                                         page */
Packit 06404a
    ogg_stream_packetin(&os,&header_comm);
Packit 06404a
    ogg_stream_packetin(&os,&header_code);
Packit 06404a
Packit 06404a
    /* This ensures the actual
Packit 06404a
     * audio data will start on a new page, as per spec
Packit 06404a
     */
Packit 06404a
    while(!eos){
Packit 06404a
      int result=ogg_stream_flush(&os,&og);
Packit 06404a
      if(result==0)break;
Packit 06404a
      fwrite(og.header,1,og.header_len,stdout);
Packit 06404a
      fwrite(og.body,1,og.body_len,stdout);
Packit 06404a
    }
Packit 06404a
Packit 06404a
  }
Packit 06404a
Packit 06404a
  while(!eos){
Packit 06404a
    long i;
Packit 06404a
    long bytes=fread(readbuffer,1,READ*4,stdin); /* stereo hardwired here */
Packit 06404a
Packit 06404a
    if(bytes==0){
Packit 06404a
      /* end of file.  this can be done implicitly in the mainline,
Packit 06404a
         but it's easier to see here in non-clever fashion.
Packit 06404a
         Tell the library we're at end of stream so that it can handle
Packit 06404a
         the last frame and mark end of stream in the output properly */
Packit 06404a
      vorbis_analysis_wrote(&vd,0);
Packit 06404a
Packit 06404a
    }else{
Packit 06404a
      /* data to encode */
Packit 06404a
Packit 06404a
      /* expose the buffer to submit data */
Packit 06404a
      float **buffer=vorbis_analysis_buffer(&vd,READ);
Packit 06404a
Packit 06404a
      /* uninterleave samples */
Packit 06404a
      for(i=0;i
Packit 06404a
        buffer[0][i]=((readbuffer[i*4+1]<<8)|
Packit 06404a
                      (0x00ff&(int)readbuffer[i*4]))/32768.f;
Packit 06404a
        buffer[1][i]=((readbuffer[i*4+3]<<8)|
Packit 06404a
                      (0x00ff&(int)readbuffer[i*4+2]))/32768.f;
Packit 06404a
      }
Packit 06404a
Packit 06404a
      /* tell the library how much we actually submitted */
Packit 06404a
      vorbis_analysis_wrote(&vd,i);
Packit 06404a
    }
Packit 06404a
Packit 06404a
    /* vorbis does some data preanalysis, then divvies up blocks for
Packit 06404a
       more involved (potentially parallel) processing.  Get a single
Packit 06404a
       block for encoding now */
Packit 06404a
    while(vorbis_analysis_blockout(&vd,&vb)==1){
Packit 06404a
Packit 06404a
      /* analysis, assume we want to use bitrate management */
Packit 06404a
      vorbis_analysis(&vb,NULL);
Packit 06404a
      vorbis_bitrate_addblock(&vb;;
Packit 06404a
Packit 06404a
      while(vorbis_bitrate_flushpacket(&vd,&op)){
Packit 06404a
Packit 06404a
        /* weld the packet into the bitstream */
Packit 06404a
        ogg_stream_packetin(&os,&op);
Packit 06404a
Packit 06404a
        /* write out pages (if any) */
Packit 06404a
        while(!eos){
Packit 06404a
          int result=ogg_stream_pageout(&os,&og);
Packit 06404a
          if(result==0)break;
Packit 06404a
          fwrite(og.header,1,og.header_len,stdout);
Packit 06404a
          fwrite(og.body,1,og.body_len,stdout);
Packit 06404a
Packit 06404a
          /* this could be set above, but for illustrative purposes, I do
Packit 06404a
             it here (to show that vorbis does know where the stream ends) */
Packit 06404a
Packit 06404a
          if(ogg_page_eos(&og))eos=1;
Packit 06404a
        }
Packit 06404a
      }
Packit 06404a
    }
Packit 06404a
  }
Packit 06404a
Packit 06404a
  /* clean up and exit.  vorbis_info_clear() must be called last */
Packit 06404a
Packit 06404a
  ogg_stream_clear(&os);
Packit 06404a
  vorbis_block_clear(&vb;;
Packit 06404a
  vorbis_dsp_clear(&vd);
Packit 06404a
  vorbis_comment_clear(&vc);
Packit 06404a
  vorbis_info_clear(&vi;;
Packit 06404a
Packit 06404a
  /* ogg_page and ogg_packet structs always point to storage in
Packit 06404a
     libvorbis.  They're never freed or manipulated directly */
Packit 06404a
Packit 06404a
  fprintf(stderr,"Done.\n");
Packit 06404a
  return(0);
Packit 06404a
}