Added speex_ctl call to set codec parameters (e.g. enable/disable
[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 #define MAX_FRAME_SIZE 2000
29
30 void usage()
31 {
32    fprintf (stderr, "speexenc [options] <input file> <output file>\n");
33    fprintf (stderr, "options:\n");
34    fprintf (stderr, "\t--help       -h      This help\n"); 
35    fprintf (stderr, "\t--version    -v      Version information\n"); 
36    fprintf (stderr, "\t--pf         --pf    Enable post-filter\n"); 
37    fprintf (stderr, "\t--no-pf      --no-pf Disable post-filter\n"); 
38 }
39
40 void version()
41 {
42    fprintf (stderr, "Speex encoder version " VERSION "\n");
43 }
44
45 int main(int argc, char **argv)
46 {
47    int c;
48    int option_index = 0;
49    char *inFile, *outFile;
50    FILE *fin, *fout;
51    short out[MAX_FRAME_SIZE];
52    float output[MAX_FRAME_SIZE];
53    int frame_size=0;
54    SpeexMode *mode=NULL;
55    void *st=NULL;
56    SpeexBits bits;
57    int first = 1;
58    struct option long_options[] =
59    {
60       {"help", no_argument, NULL, 0},
61       {"version", no_argument, NULL, 0},
62       {"pf", no_argument, NULL, 0},
63       {"no-pf", no_argument, NULL, 0},
64       {0, 0, 0, 0}
65    };
66    ogg_sync_state oy;
67    ogg_page       og;
68    ogg_packet     op;
69    ogg_stream_state os;
70    int pf_enabled;
71
72    pf_enabled = 0;
73
74    /*Process options*/
75    while(1)
76    {
77       c = getopt_long (argc, argv, "hv",
78                        long_options, &option_index);
79       if (c==-1)
80          break;
81       
82       switch(c)
83       {
84       case 0:
85          if (strcmp(long_options[option_index].name,"help")==0)
86          {
87             usage();
88             exit(0);
89          } else if (strcmp(long_options[option_index].name,"version")==0)
90          {
91             version();
92             exit(0);
93          } else if (strcmp(long_options[option_index].name,"pf")==0)
94          {
95             pf_enabled=1;
96          } else if (strcmp(long_options[option_index].name,"no-pf")==0)
97          {
98             pf_enabled=0;
99          }
100          break;
101       case 'h':
102          usage();
103          break;
104       case 'v':
105          version();
106          exit(0);
107          break;
108       case '?':
109          usage();
110          exit(1);
111          break;
112       }
113    }
114    if (argc-optind!=2)
115    {
116       usage();
117       exit(1);
118    }
119    inFile=argv[optind];
120    outFile=argv[optind+1];
121    
122    /*Open input file*/
123    if (strcmp(inFile, "-")==0)
124       fin=stdin;
125    else 
126    {
127       fin = fopen(inFile, "r");
128       if (!fin)
129       {
130          perror(inFile);
131          exit(1);
132       }
133    }
134
135    /*Open output file*/
136    if (strcmp(outFile,"-")==0)
137       fout=stdout;
138    else 
139    {
140       fout = fopen(outFile, "w");
141       if (!fout)
142       {
143          perror(outFile);
144          exit(1);
145       }
146    }
147
148    /*Init Ogg data struct*/
149    ogg_sync_init(&oy);
150    ogg_stream_init(&os, 0);
151    
152    speex_bits_init(&bits);
153    /*Main decoding loop*/
154    while (1)
155    {
156       char *data;
157       int i, nb_read;
158       /*Get the ogg buffer for writing*/
159       data = ogg_sync_buffer(&oy, 200);
160       /*Read bitstream from input file*/
161       nb_read = fread(data, sizeof(char), 200, fin);      
162       ogg_sync_wrote(&oy, nb_read);
163
164       /*Loop for all complete pages we got (most likely only one)*/
165       while (ogg_sync_pageout(&oy, &og)==1)
166       {
167          /*Add page to the bitstream*/
168          ogg_stream_pagein(&os, &og);
169          /*Extract all available packets*/
170          while (ogg_stream_packetout(&os, &op)==1)
171          {
172             /*If first packet, process as Speex header*/
173             if (first)
174             {
175                if (strncmp((char *)op.packet, "speex wideband**", 12)==0)
176                {
177                   mode = &speex_wb_mode;
178                } else if (strncmp((char *)op.packet, "speex narrowband", 12)==0)
179                {
180                   mode = &speex_nb_mode;
181                } else {
182                   fprintf (stderr, "This Ogg file is not a Speex bitstream\n");
183                   exit(1);
184                }
185                /*Initialize Speex decoder*/
186                st = speex_decoder_init(mode);
187                speex_ctl(st, SPEEX_SET_PF, &pf_enabled);
188                frame_size=mode->frameSize;
189                first=0;
190             } else {
191                /*End of stream condition*/
192                if (strncmp((char *)op.packet, "END OF STREAM", 13)==0)
193                   break;
194                /*Copy Ogg packet to Speex bitstream*/
195                speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
196                /*Decode a frame*/
197                speex_decode(st, &bits, output, 0);
198                
199                /*PCM saturation (just in case)*/
200                for (i=0;i<frame_size;i++)
201                {
202                   if (output[i]>32000)
203                      output[i]=32000;
204                   else if (output[i]<-32000)
205                      output[i]=-32000;
206                }
207                /*Convert to short and save to output file*/
208                for (i=0;i<frame_size;i++)
209                   out[i]=output[i];
210                fwrite(out, sizeof(short), frame_size, fout);
211             }
212          }
213       }
214       if (feof(fin))
215          break;
216
217    }
218
219    speex_decoder_destroy(st);
220    speex_bits_destroy(&bits);
221    ogg_stream_clear(&os);
222  
223    exit(0);
224    return 1;
225 }