Less warnings...
[speexdsp.git] / src / speexdec.c
1 /* Copyright (C) 2002 Jean-Marc Valin 
2    File: speexdec.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 #ifdef HAVE_SYS_SOUNDCARD_H
29 #include <sys/soundcard.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <sys/ioctl.h>
34 #endif
35
36 #include <string.h>
37 #include "wav_io.h"
38
39 #define MAX_FRAME_SIZE 2000
40
41 FILE *out_file_open(char *outFile, int rate)
42 {
43    FILE *fout;
44    /*Open output file*/
45    if (strlen(outFile)==0)
46    {
47 #ifdef HAVE_SYS_SOUNDCARD_H
48       int audio_fd, format, stereo;
49       audio_fd=open("/dev/dsp", O_WRONLY);
50       
51       format=AFMT_S16_LE;
52       if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1)
53       {
54          perror("SNDCTL_DSP_SETFMT");
55          close(audio_fd);
56          exit(1);
57       }
58       
59       stereo=0;
60       if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1)
61       {
62          perror("SNDCTL_DSP_STEREO");
63          close(audio_fd);
64          exit(1);
65       }
66       if (stereo!=0)
67       {
68          fprintf (stderr, "Cannot set mono mode\n");
69          exit(1);
70       }
71
72       if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate)==-1)
73       {
74          perror("SNDCTL_DSP_SPEED");
75          close(audio_fd);
76          exit(1);
77       }
78       fout = fdopen(audio_fd, "w");
79 #else
80       fprintf (stderr, "No soundcard support\n");
81       exit(1);
82 #endif
83    } else {
84       if (strcmp(outFile,"-")==0)
85          fout=stdout;
86       else 
87       {
88          fout = fopen(outFile, "w");
89          if (!fout)
90          {
91             perror(outFile);
92             exit(1);
93          }
94          if (strcmp(outFile+strlen(outFile)-4,".wav")==0)
95             write_wav_header(fout, rate, 1, 0, 0);
96       }
97    }
98    return fout;
99 }
100
101 void usage()
102 {
103    fprintf (stderr, "speexenc [options] <input file> <output file>\n");
104    fprintf (stderr, "options:\n");
105    fprintf (stderr, "\t--help       -h      This help\n"); 
106    fprintf (stderr, "\t--version    -v      Version information\n"); 
107    fprintf (stderr, "\t--pf         --pf    Enable post-filter\n"); 
108    fprintf (stderr, "\t--no-pf      --no-pf Disable post-filter\n"); 
109 }
110
111 void version()
112 {
113    fprintf (stderr, "Speex decoder version " VERSION "\n");
114 }
115
116 int main(int argc, char **argv)
117 {
118    int c;
119    int option_index = 0;
120    char *inFile, *outFile;
121    FILE *fin, *fout=NULL;
122    short out[MAX_FRAME_SIZE];
123    float output[MAX_FRAME_SIZE];
124    int frame_size=0;
125    SpeexMode *mode=NULL;
126    void *st=NULL;
127    SpeexBits bits;
128    int first = 1;
129    struct option long_options[] =
130    {
131       {"help", no_argument, NULL, 0},
132       {"version", no_argument, NULL, 0},
133       {"pf", no_argument, NULL, 0},
134       {"no-pf", no_argument, NULL, 0},
135       {0, 0, 0, 0}
136    };
137    ogg_sync_state oy;
138    ogg_page       og;
139    ogg_packet     op;
140    ogg_stream_state os;
141    int pf_enabled;
142
143    pf_enabled = 0;
144
145    /*Process options*/
146    while(1)
147    {
148       c = getopt_long (argc, argv, "hv",
149                        long_options, &option_index);
150       if (c==-1)
151          break;
152       
153       switch(c)
154       {
155       case 0:
156          if (strcmp(long_options[option_index].name,"help")==0)
157          {
158             usage();
159             exit(0);
160          } else if (strcmp(long_options[option_index].name,"version")==0)
161          {
162             version();
163             exit(0);
164          } else if (strcmp(long_options[option_index].name,"pf")==0)
165          {
166             pf_enabled=1;
167          } else if (strcmp(long_options[option_index].name,"no-pf")==0)
168          {
169             pf_enabled=0;
170          }
171          break;
172       case 'h':
173          usage();
174          break;
175       case 'v':
176          version();
177          exit(0);
178          break;
179       case '?':
180          usage();
181          exit(1);
182          break;
183       }
184    }
185    if (argc-optind!=2 && argc-optind!=1)
186    {
187       usage();
188       exit(1);
189    }
190    inFile=argv[optind];
191
192    if (argc-optind==2)
193       outFile=argv[optind+1];
194    else
195       outFile = "";
196    /*Open input file*/
197    if (strcmp(inFile, "-")==0)
198       fin=stdin;
199    else 
200    {
201       fin = fopen(inFile, "r");
202       if (!fin)
203       {
204          perror(inFile);
205          exit(1);
206       }
207    }
208
209
210    /*Init Ogg data struct*/
211    ogg_sync_init(&oy);
212    ogg_stream_init(&os, 0);
213    
214    speex_bits_init(&bits);
215    /*Main decoding loop*/
216    while (1)
217    {
218       char *data;
219       int i, nb_read;
220       /*Get the ogg buffer for writing*/
221       data = ogg_sync_buffer(&oy, 200);
222       /*Read bitstream from input file*/
223       nb_read = fread(data, sizeof(char), 200, fin);      
224       ogg_sync_wrote(&oy, nb_read);
225
226       /*Loop for all complete pages we got (most likely only one)*/
227       while (ogg_sync_pageout(&oy, &og)==1)
228       {
229          /*Add page to the bitstream*/
230          ogg_stream_pagein(&os, &og);
231          /*Extract all available packets*/
232          while (ogg_stream_packetout(&os, &op)==1)
233          {
234             /*If first packet, process as Speex header*/
235             if (first)
236             {
237                int rate;
238                if (strncmp((char *)op.packet, "speex wideband**", 12)==0)
239                {
240                   rate=16000;
241                   mode = &speex_wb_mode;
242                } else if (strncmp((char *)op.packet, "speex narrowband", 12)==0)
243                {
244                   rate=8000;
245                   mode = &speex_nb_mode;
246                } else {
247                   fprintf (stderr, "This Ogg file is not a Speex bitstream\n");
248                   exit(1);
249                }
250                /*Initialize Speex decoder*/
251                st = speex_decoder_init(mode);
252                speex_decoder_ctl(st, SPEEX_SET_PF, &pf_enabled);
253                speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size);
254
255                fout = out_file_open(outFile, rate);
256
257                first=0;
258             } else {
259                /*End of stream condition*/
260                if (strncmp((char *)op.packet, "END OF STREAM", 13)==0)
261                   break;
262                /*Copy Ogg packet to Speex bitstream*/
263                speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
264                /*Decode a frame*/
265                speex_decode(st, &bits, output, 0);
266                
267                /*PCM saturation (just in case)*/
268                for (i=0;i<frame_size;i++)
269                {
270                   if (output[i]>32000)
271                      output[i]=32000;
272                   else if (output[i]<-32000)
273                      output[i]=-32000;
274                }
275                /*Convert to short and save to output file*/
276                for (i=0;i<frame_size;i++)
277                   out[i]=output[i];
278                fwrite(out, sizeof(short), frame_size, fout);
279             }
280          }
281       }
282       if (feof(fin))
283          break;
284
285    }
286
287    speex_decoder_destroy(st);
288    speex_bits_destroy(&bits);
289    ogg_stream_clear(&os);
290  
291    exit(0);
292    return 1;
293 }