speexenc and speexdec now use the Ogg bitstream. This is very preliminary
[speexdsp.git] / src / speexenc.c
1 /* Copyright (C) 2002 Jean-Marc Valin 
2    File: speexenc.c
3
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8    
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13    
14    You should have received a copy of the GNU Lesser General Public
15    License along with this library; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <getopt.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "speex.h"
26 #include <ogg/ogg.h>
27
28 int oe_write_page(ogg_page *page, FILE *fp)
29 {
30         int written;
31         written = fwrite(page->header,1,page->header_len, fp);
32         written += fwrite(page->body,1,page->body_len, fp);
33
34         return written;
35 }
36
37 #define MAX_FRAME_SIZE 2000
38 #define MAX_FRAME_BYTES 1000
39
40 void usage()
41 {
42    fprintf (stderr, "speexenc [options] <input file> <output file>\n");
43    fprintf (stderr, "options:\n");
44    fprintf (stderr, "\t--narrowband -n    Narrowband (8 kHz) input file\n"); 
45    fprintf (stderr, "\t--wideband   -w    Wideband (16 kHz) input file\n"); 
46    fprintf (stderr, "\t--help       -h    This help\n"); 
47    fprintf (stderr, "\t--version    -v    Version information\n"); 
48    fprintf (stderr, "\nInput must be raw audio (no header), 16 bits\n"); 
49 }
50
51 void version()
52 {
53    fprintf (stderr, "Speex encoder version " VERSION "\n");
54 }
55
56 int main(int argc, char **argv)
57 {
58    int c;
59    int option_index = 0;
60    int narrowband=0, wideband=0;
61    char *inFile, *outFile;
62    FILE *fin, *fout;
63    short in[MAX_FRAME_SIZE];
64    float input[MAX_FRAME_SIZE];
65    int frame_size;
66    int i,nbBytes;
67    SpeexMode *mode=NULL;
68    void *st;
69    FrameBits bits;
70    char cbits[MAX_FRAME_BYTES];
71    struct option long_options[] =
72    {
73       {"wideband", no_argument, NULL, 0},
74       {"narrowband", no_argument, NULL, 0},
75       {"help", no_argument, NULL, 0},
76       {"version", no_argument, NULL, 0},
77       {0, 0, 0, 0}
78    };
79    /*ogg_stream_state *ogg_state;
80    ogg_packet packet;
81    ogg_page page;*/
82
83    ogg_stream_state os;
84    ogg_page              og;
85    ogg_packet            op;
86    int bytes_written, ret, result;
87    int id=0;
88
89    while(1)
90    {
91       c = getopt_long (argc, argv, "nwhv",
92                        long_options, &option_index);
93       if (c==-1)
94          break;
95       
96       switch(c)
97       {
98       case 0:
99          if (strcmp(long_options[option_index].name,"narrowband")==0)
100             narrowband=1;
101          else if (strcmp(long_options[option_index].name,"wideband")==0)
102                wideband=1;
103          else if (strcmp(long_options[option_index].name,"help")==0)
104          {
105             usage();
106             exit(0);
107          } else if (strcmp(long_options[option_index].name,"version")==0)
108          {
109             version();
110             exit(0);
111          }
112          break;
113       case 'n':
114          narrowband=1;
115          break;
116       case 'h':
117          usage();
118          break;
119       case 'v':
120          version();
121          exit(0);
122          break;
123       case 'w':
124          wideband=1;
125          break;
126       case '?':
127          usage();
128          exit(1);
129          break;
130       }
131    }
132    if (argc-optind!=2)
133    {
134       usage();
135       exit(1);
136    }
137    inFile=argv[optind];
138    outFile=argv[optind+1];
139
140    if (ogg_stream_init(&os, 0)==-1)
141    {
142       fprintf(stderr,"Stream init failed\n");
143       exit(1);
144    }
145
146    if (wideband && narrowband)
147    {
148       fprintf (stderr,"Cannot specify both wideband and narrowband at the same time\n");
149       exit(1);
150    };
151    if (!wideband)
152       narrowband=1;
153    if (narrowband)
154       mode=&speex_nb_mode;
155    if (wideband)
156       mode=&speex_wb_mode;
157
158    st = encoder_init(mode);
159
160    if (strcmp(inFile, "-")==0)
161       fin=stdin;
162    else 
163    {
164       fin = fopen(inFile, "r");
165       if (!fin)
166       {
167          perror(inFile);
168          exit(1);
169       }
170    }
171    if (strcmp(outFile,"-")==0)
172       fout=stdout;
173    else 
174    {
175       fout = fopen(outFile, "w");
176       if (!fout)
177       {
178          perror(outFile);
179          exit(1);
180       }
181    }
182
183    /*Temporary header*/
184    {
185       char *header="";
186       /*if (narrowband)
187          header="spexn";
188       if (wideband)
189       header="spexw";*/
190
191       if (narrowband)
192          op.packet = (unsigned char *)"speex narrowband";
193       if (wideband)
194          op.packet = (unsigned char *)"speex wideband**";
195       op.bytes = 16;
196       op.b_o_s = 1;
197       op.e_o_s = 0;
198       op.granulepos = 0;
199       op.packetno = 0;
200       ogg_stream_packetin(&os, &op);
201
202       while((result = ogg_stream_flush(&os, &og)))
203       {
204          if(!result) break;
205          ret = oe_write_page(&og, fout);
206          if(ret != og.header_len + og.body_len)
207          {
208             fprintf (stderr,"Failed writing header to output stream\n");
209             exit(1);
210          }
211          else
212             bytes_written += ret;
213       }
214       
215       
216       if (fwrite(header, 1, 5, fout)!=5)
217       {
218          perror("Cannot write header");
219       }
220    }
221
222    frame_size=mode->frameSize;
223
224    while (1)
225    {
226       id++;
227       fread(in, sizeof(short), frame_size, fin);
228       if (feof(fin))
229          break;
230       for (i=0;i<frame_size;i++)
231          input[i]=in[i];
232       encode(st, input, &bits);
233
234       /*if (id%5!=0)
235         continue;*/
236       nbBytes = speex_bits_write(&bits, cbits, 500);
237       speex_bits_reset(&bits);
238       op.packet = (unsigned char *)cbits;
239       op.bytes = nbBytes;
240       op.b_o_s = 0;
241       op.e_o_s = 0;
242       op.granulepos = id;
243       op.packetno = id;
244       ogg_stream_packetin(&os, &op);
245
246       while (ogg_stream_pageout(&os,&og))
247       {
248          ret = oe_write_page(&og, fout);
249          if(ret != og.header_len + og.body_len)
250          {
251             fprintf (stderr,"Failed writing header to output stream\n");
252             exit(1);
253          }
254          else
255             bytes_written += ret;
256       }
257    }
258    
259    op.packet = (unsigned char *)"END OF STREAM";
260    op.bytes = 13;
261    op.b_o_s = 0;
262    op.e_o_s = 1;
263    op.granulepos = id+1;
264    op.packetno = id+1;
265    ogg_stream_packetin(&os, &op);
266    while (ogg_stream_flush(&os, &og))
267    {
268       ret = oe_write_page(&og, fout);
269       if(ret != og.header_len + og.body_len)
270       {
271          fprintf (stderr,"Failed writing header to output stream\n");
272          exit(1);
273       }
274       else
275          bytes_written += ret;
276    }
277    
278
279    encoder_destroy(st);
280
281    ogg_stream_clear(&os);
282
283    exit(0);
284    return 1;
285 }
286