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