Addition of win32 support to the examples (changing stdin/stdout to binary
[platform/upstream/libvorbis.git] / examples / encoder_example.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5  * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
6  * PLEASE READ THESE TERMS DISTRIBUTING.                            *
7  *                                                                  *
8  * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000             *
9  * by Monty <monty@xiph.org> and The XIPHOPHORUS Company            *
10  * http://www.xiph.org/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: simple example encoder
15  last mod: $Id: encoder_example.c,v 1.7 2000/05/12 08:38:20 msmith Exp $
16
17  ********************************************************************/
18
19 /* takes a stereo 16bit 44.1kHz WAV file from stdin and encodes it into
20    a Vorbis bitstream */
21
22 /* Note that this is POSIX, not ANSI, code */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <time.h>
27 #include <math.h>
28 #include "vorbis/modes.h"
29
30 #ifdef _WIN32 /* We need the following two to set stdin/stdout to binary */
31 #include <io.h>
32 #include <fcntl.h>
33 #endif
34
35
36 #define READ 1024
37 signed char readbuffer[READ*4+44]; /* out of the data segment, not the stack */
38
39 int main(){
40   ogg_stream_state os; /* take physical pages, weld into a logical
41                           stream of packets */
42   ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
43   ogg_packet       op; /* one raw packet of data for decode */
44   
45   vorbis_info     *vi; /* struct that stores all the static vorbis bitstream
46                           settings */
47   vorbis_comment   vc; /* struct that stores all the user comments */
48
49   vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
50   vorbis_block     vb; /* local working space for packet->PCM decode */
51
52   int eos=0;
53
54   /* we cheat on the WAV header; we just bypass 44 bytes and never
55      verify that it matches 16bit/stereo/44.1kHz.  This is just an
56      example, after all. */
57
58 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
59   /* Beware the evil ifdef. We avoid these where we can, but this one we 
60      cannot. Don't add any more, you'll probably go to hell if you do. */
61   _setmode( _fileno( stdin ), _O_BINARY );
62   _setmode( _fileno( stdout ), _O_BINARY );
63 #endif
64
65
66   fread(readbuffer,1,44,stdin);
67
68   /********** Encode setup ************/
69
70   /* choose an encoding mode */
71   /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
72   vi=&info_A;
73
74   /* add a comment */
75   vorbis_comment_init(&vc);
76   vorbis_comment_add(&vc,"Track encoded by encoder_example.c");
77
78   /* set up the analysis state and auxiliary encoding storage */
79   vorbis_analysis_init(&vd,vi);
80   vorbis_block_init(&vd,&vb);
81   
82   /* set up our packet->stream encoder */
83   /* pick a random serial number; that way we can more likely build
84      chained streams just by concatenation */
85   srand(time(NULL));
86   ogg_stream_init(&os,rand());
87
88   /* Vorbis streams begin with three headers; the initial header (with
89      most of the codec setup parameters) which is mandated by the Ogg
90      bitstream spec.  The second header holds any comment fields.  The
91      third header holds the bitstream codebook.  We merely need to
92      make the headers, then pass them to libvorbis one at a time;
93      libvorbis handles the additional Ogg bitstream constraints */
94
95   {
96     ogg_packet header;
97     ogg_packet header_comm;
98     ogg_packet header_code;
99
100     vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
101     ogg_stream_packetin(&os,&header); /* automatically placed in its own
102                                          page */
103     ogg_stream_packetin(&os,&header_comm);
104     ogg_stream_packetin(&os,&header_code);
105
106     /* no need to write out here.  We'll get to that in the main loop */
107   }
108   
109   while(!eos){
110     long i;
111     long bytes=fread(readbuffer,1,READ*4,stdin); /* stereo hardwired here */
112
113     if(bytes==0){
114       /* end of file.  this can be done implicitly in the mainline,
115          but it's easier to see here in non-clever fashion.
116          Tell the library we're at end of stream so that it can handle
117          the last frame and mark end of stream in the output properly */
118       vorbis_analysis_wrote(&vd,0);
119
120     }else{
121       /* data to encode */
122
123       /* expose the buffer to submit data */
124       double **buffer=vorbis_analysis_buffer(&vd,READ);
125       
126       /* uninterleave samples */
127       for(i=0;i<bytes/4;i++){
128         buffer[0][i]=((readbuffer[i*4+1]<<8)|
129                       (0x00ff&(int)readbuffer[i*4]))/32768.;
130         buffer[1][i]=((readbuffer[i*4+3]<<8)|
131                       (0x00ff&(int)readbuffer[i*4+2]))/32768.;
132       }
133     
134       /* tell the library how much we actually submitted */
135       vorbis_analysis_wrote(&vd,i);
136     }
137
138     /* vorbis does some data preanalysis, then divvies up blocks for
139        more involved (potentially parallel) processing.  Get a single
140        block for encoding now */
141     while(vorbis_analysis_blockout(&vd,&vb)==1){
142
143       /* analysis */
144       vorbis_analysis(&vb,&op);
145
146       /* weld the packet into the bitstream */
147       ogg_stream_packetin(&os,&op);
148
149       /* write out pages (if any) */
150       while(!eos){
151         int result=ogg_stream_pageout(&os,&og);
152         if(result==0)break;
153         fwrite(og.header,1,og.header_len,stdout);
154         fwrite(og.body,1,og.body_len,stdout);
155
156         /* this could be set above, but for illustrative purposes, I do
157            it here (to show that vorbis does know where the stream ends) */
158         
159         if(ogg_page_eos(&og))eos=1;
160
161       }
162     }
163   }
164
165   /* clean up and exit.  vorbis_info_clear() must be called last */
166   
167   ogg_stream_clear(&os);
168   vorbis_block_clear(&vb);
169   vorbis_dsp_clear(&vd);
170   
171   /* ogg_page and ogg_packet structs always point to storage in
172      libvorbis.  They're never freed or manipulated directly */
173   
174   fprintf(stderr,"Done.\n");
175   return(0);
176 }
177