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