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